自己写了一个简洁版本, 加注释。
第一个函数是得到KMP的next数组。
next数组本质:在两个字符串不匹配时,T串能根据当前索引的next值跳转到T串对应位置。
1、设置next的第一个值为-1。
2、遍历剩下的T串
3、T串前后比较,相等就在next中对应位置加1
4、不等,就回溯 T串中等价位置
void getNext(string &T,int *next)
{
int i = 0, j = -1;
next[0] = -1;
while (i < T.size() -1)
{
if (j == -1|| T[i] == T[j])
{
i++;
j++;
if (T[i] != T[j])
next[i] = j;
//优化点,防止T串为aaaab这种类型,需要一个一个往前翻,利用下面两行,可以直接找到最初等价位置
else
next[i] = next[j];
}
else
j = next[j];
}
}
第二个 即为KMP函数
1、首先生成next数组
2、对S串、T串进行遍历
3、相等时 继续往前走
4、不等时且此时对应的 next值为-1 时,代表此时T串又回到了第一个位置,并且S串、T串该处不匹配
5、其他情况时将next值赋给T串的移动变量j
6、释放next
7、如果j已经走到了T串尾,则表示已经S串、T串已经各处匹配,返回i-j
不然,匹配失败,返回-1
int KMP_method(string &S, string &T)//S为源串,T为目标串
{
int *next = new int[T.size()];
getNext(T, next);
int i = 0, j = 0;
while (i < S.size() && j < T.size())
{
if (S[i] == T[j])
{
i++;
j++;
}
else if (next[j] == -1)
i++;
else
j = next[j];
}
if (next)
{
delete[]next;
next = NULL;
}
return (j == T.size()) ? i -j : -1;
}