Arrays 从排序字符串数组中查找第一个前缀匹配的最有效算法是什么?
输入: 1) 字符串SA的巨大排序数组 2) 前缀字符串p 输出: 与输入前缀匹配的第一个字符串的索引(如果有)。 如果没有这样的匹配,那么输出将是-1 例如:Arrays 从排序字符串数组中查找第一个前缀匹配的最有效算法是什么?,arrays,string,algorithm,sorting,search,Arrays,String,Algorithm,Sorting,Search,输入: 1) 字符串SA的巨大排序数组 2) 前缀字符串p 输出: 与输入前缀匹配的第一个字符串的索引(如果有)。 如果没有这样的匹配,那么输出将是-1 例如: SA = {"ab", "abd", "abdf", "abz"} P = "abd" 输出应为1(索引从0开始) 做这类工作最有效的算法是什么?FreeBSD内核使用a作为其路由表,您应该检查一下。这只是一个修改过的对分搜索: 只检查每个元素中与搜索字符串中相同数量的字符;及 如果找到匹配项,请继续向后搜索(线性搜索或进一步二分法
SA = {"ab", "abd", "abdf", "abz"}
P = "abd"
输出应为1(索引从0开始)
做这类工作最有效的算法是什么?FreeBSD内核使用a作为其路由表,您应该检查一下。这只是一个修改过的对分搜索:
- 只检查每个元素中与搜索字符串中相同数量的字符;及
- 如果找到匹配项,请继续向后搜索(线性搜索或进一步二分法搜索),直到找到不匹配的结果,然后返回最后一个匹配结果的索引
例如,前缀为“abd”,请尝试查找虚拟前缀“abc(255)”。(255)仅表示最大字符数。找到“abc(255)”后,下一个单词应该是与“abd”匹配的第一个单词如果有的话。如果您只想这样做一次,那么另一方面,如果您需要对许多不同的前缀(但在同一个字符串数组上)执行此操作,那么构建一个数组可能是一个好主意,在构建完树后,每次查找都会非常快。您是否能够预先计算所有可能的前缀
如果是这样,您可以这样做,然后使用二进制搜索在预先计算的表中查找前缀。使用前缀存储所需值的下标。我的解决方案: 使用二进制搜索
private static int search(String[] words, String searchPrefix) {
if (words == null || words.length == 0) {
return -1;
}
int low = 0;
int high = words.length - 1;
int searchPrefixLength = searchPrefix.length();
while (low <= high) {
int mid = low + (high - low) / 2;
String word = words[mid];
int compare = -1;
if (searchPrefixLength <= word.length()) {
compare = word.substring(0, searchPrefixLength).compareTo(searchPrefix);
}
if (compare == 0) {
return mid;
} else if (compare > 0) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
private静态整型搜索(String[]单词,String searchPrefix){
if(words==null | | words.length==0){
返回-1;
}
int低=0;
int-high=单词长度-1;
int searchPrefixLength=searchPrefix.length();
而(low这里是一个可能的解决方案(在Python中),它具有O(k.log(n))时间复杂度和O(1)额外的空间复杂度(考虑到n个字符串和k个前缀长度)
其基本原理是执行二进制搜索,只考虑字符串的给定字符索引。如果存在这些索引,则继续下一个字符索引。如果在任何字符串中找不到任何前缀字符,则会立即返回
输入导入列表中的
def first(项目:列表[str],前缀:str,i:int,c:str,左:int,右:int):
结果=-1
左=len(项目[mid]):
左=中+1
elif(c<项目[mid][i]):
右=中-1
elif(c>项目[mid][i]):
左=中+1
其他:
结果=中
右=中-1
返回结果
def last(项目:列表[str],前缀:str,i:int,c:str,左:int,右:int):
结果=-1
左=len(项目[mid]):
左=中+1
elif(c<项目[mid][i]):
右=中-1
elif(c>项目[mid][i]):
左=中+1
其他:
结果=中
左=中+1
返回结果
def是前缀(项目:列表[str],前缀:str):
左=0
右=透镜(项目)-1
对于范围内的i(len(前缀)):
c=前缀[i]
左=第一(项目、前缀、i、c、左、右)
右=最后(项目、前缀、i、c、左、右)
如果(左==-1或右==-1):
返回错误
返回真值
#测试用例
a=['ab','abjsiohjd','abikshdiu','ashdi','abcde Aasioudhf','abcdefgOAJ','aa','aaap','aas','asd','BBBBBBB','BSADIJH','iod','0asdn','asdjd','bqw','ba']
a、 排序()
印刷品(a)
打印(是前缀(a,'abcdf'))
打印(是前缀(a,'abcde'))
打印(是前缀(a,'abcdef'))
打印(是前缀(a,'abcdefg'))
打印(是前缀(a,'abcdefgh'))
打印(是前缀(a,'abcde Aa'))
打印(是_前缀(a,'iod'))
打印(是_前缀(a,'zzzz-iod'))
这一要点在基树的最佳案例查找时间是O(n),其中n是字符数,而二进制搜索则是O(log m),其中m是列表的大小。基数搜索速度不一定会更快。蜘蛛纲:这不是真的。即使在最佳案例(存在匹配)中,二进制搜索也是O(n+logm),因为它必须读取整个前缀以检查是否匹配。在最坏的情况下,它是O(nlogm)。@Arachnid:+1表示布赖恩的评论,加上O(n)是对基数树的最坏情况查找,其中存在匹配项,您需要读取整个前缀。好吧,二进制搜索几乎不需要实现,并且不需要额外内存。基数树实现起来很复杂,需要额外内存,好处也不多。sortedIndex使其更简单:)他还可以在线性时间内将前缀与每个元素进行比较。没错,但如果他要检查多个前缀,那不是个好主意。