void GetNext(string pattern,int* &next)
{
int length = pattern.length(); //*前后缀相等的长度越大意味着在该位置回退回去的距离越短,效率越低,next数组内的数字代表当前不匹配,用该数字索引对应的字符重新匹配
next = new int[length];
int k = -1, j = 0; //k代表前缀结尾,j代表后缀结尾
next[0] = -1; //很关键,因为next[0]为-1意味着此处没有前缀和后缀
while(j < length)
{
if(k == -1 || pattern[j] == pattern[k])
{
next[++j] = ++k; //j和k先自加1,从next[1]开始写入数据
}
else
{
k = next[k]; //此次前缀和后缀不匹配,前缀缩小范围,根据已有的next数组信息,可以明确到具体缩小到的位置,即next[k],next[k]本身的意思就是适配的时候应该回到next[k]处重新匹配,刚好满足条件。
}
}
}
int KMP(string str,string pattern, int next[])
{
int strL = str.length();
int patternL = pattern.length();
int i = 0, j = 0;
while(i < strL && j < patternL)
{
if(j == -1 || str[i] == pattern[j]) //如果第0位pattern就跟str不匹配,j=next[0]=-1.要考虑此情况
{
i++;
j++;
}
else
{
j = next[j];
}
}
return i < strL ? i - j : -1; //返回-1则未找到匹配位置
}
优化版kmp算法:
void GetNextEX(string pattern,int* &next)
{
int length = pattern.length();
next = new int[length];
int k = -1, j = 0;
next[0] = -1;
while(j < length)
{
if(k == -1 || pattern[j] == pattern[k])
{
j++;
k++;
if(pattern[j] == pattern[k])//next[j]=k的含义是,如果在j处匹配失败,则回溯到k重新匹配,可是预判一下,如果模式串里第j个字符跟第k个字符相等,j对应字符都失配了,k对应那个肯定也适配,这种直接继续回溯到next[k],k不用看了
{
next[j] = next[k];
}
else
{
next[j] = k;
}
}
else
{
k = next[k];
}
}
}
KMP算法原始版与优化
最新推荐文章于 2024-05-04 10:03:35 发布