【发布时间】:2020-05-13 05:00:30
【问题描述】:
所以我一直在研究子字符串搜索算法,发现大多数算法(如 kmp 和 rabin-karp 算法)在进行一些字符串匹配之前需要额外的时间复杂度来进行预处理。这样做有什么好处吗?为什么他们不直接跳到字符串匹配,以使大 O 时间复杂度不会下降到 O(m+n)? 我尝试通过简单地跳过预处理时间来创建一个我认为是 O(n) 的子字符串算法(如果我错了,请纠正我)。我想知道为什么人们不这样做,请参考下面的C代码。
int search(char hay[], char needle[], int hayLen, int needleLen){
int found;
int i = 0;
while (i < (hayLen - needleLen + 1)){
if (hay[i] == needle[0]){
found = 1;
for (int j=0; j<needleLen; j++){
if (hay[i] != needle[j]){
found = 0;
break;
}
i++;
}
if (found)
return i - needleLen;
}
else
i++;
}
return -1;
}
编辑:
删除了 strlen 函数以避免任何不必要的时间复杂度
【问题讨论】:
-
如果你关心性能,你应该做的第一件事就是从你的循环中取出所有那些恒定的
strlen()调用,并在进入任何循环之前对它们进行一次评估。 -
不确定 Rabin-Karp,但 KMP 是高效的,因为预处理允许它在输入中向前跳过并绕过许多比较。
-
你在这里调用了很多
strlen,这对于应该是高性能的代码来说是相当惩罚的。这些值不会改变。在函数开始时将它们捕获到变量中。每个strlen()调用本身都是O(n)! -
当您对 'haystack' 中的每个字符重复迭代 'needle' 时,最终会花费 O(nm) 时间。想象一下如果 'needle' 是 'a...ab' 而 haystack 是 'a...a' 会发生什么(两个很长的字符串都有很多 a)。比 O(n+m) 差很多
-
你不需要传入这些值,你可以随时计算它们。
标签: c algorithm substring knuth-morris-pratt rabin-karp