简单的kmp算法,如何实现?自己想的和教科书上的有何区别?复杂度是O(m+n)? 真的很简单? 仅仅是模式匹配算法的一个开篇而已,下面给出我自己想着写的与教科书上的差异吧?
我写的get_next算法
bool get_next(char * find, int len, int * next)
{
memset(next, 0, sizeof(int) * len);
next[0] = -1;
if(len == 1)
return true;
for(int i = 2; i < len; i++)
{
int j = i - 1;
while(next[j] != -1)
{
if(find[i - 1] == find[next[j]])
{
next[i] = next[j] + 1;
break;
}
j = next[j];
}
}
return true;
}
教科书原版
//这是整个kmp中最核心的地方
int get_next(const char*t, int *next)
{
int i = 0;
int j = -1; //设置j = -1,非常巧妙
int len = strlen(t);
memset(next,0, sizeof(int) * len);
next[0] = -1;
while(i < len - 1)
{
if(j == -1 || t[i] == t[j]) //前面的判断,j == -1, 非常巧妙
{
i++;
j++;
next[i] = j; //将后面的next数组元素赋值
}
else
j = next[j];
}
}
对比
自己在循环比例 next时,使用了另外一个while,而标准版里是使用外层循环,只不过内层在遍历的时候外层index不变,比较巧妙的设计方法,代码美观上增色不少,其实时间复杂度都是一样的。
看起来算法的复杂度是O(m+n)其实是不准确的,因为每次查询都有可能会走lg(m)的深度,所以我觉得最大的复杂度是O(lg(m)n+n)