字符串模式匹配
next数组求解
以求c字符之前的最长公共前后缀为例,先假定len为3。
前缀对应aba,后缀对应bab,由于前缀第一个字符a 不等于 后缀第一个字符 b,显然len应该减1
len减一之后,前缀对应ab,后缀对应ab,见下图。
则len定为2,next[j]=2。即next[4]=2;
全部代码如下:
#include <iostream>
#include <cstring>
using namespace std;
void GetNext(char T[], int next[])
{
int i, j, len;
next[0] = -1; //next[0] 设置为 -1
for (j = 1; T[j] != '\0'; j++) //依次求 next[j]
{
for (len = j - 1; len >= 1; len--) //先假定最长公共前后缀len为j-1,不满足条件则将len--
{
for (i = 0; i < len; i++) //依次比较T[i] 与 T[j - len + 1] 若相等则继续向后比较,不等就跳出。
{
if (T[i] != T[j - len + i])
{
break;
}
}
if (i == len) //如果i与len相等,则表明next[j]=len
{
next[j] = len;
break;
}
}
if (len < 1) //len<1,则表明next[j]=0;
{
next[j] = 0;
}
}
}
int KMP(char S[], char T[])
{
int i = 0, j = 0;
int next[80];
GetNext(T, next);
while (S[i] != '\0' && T[j] != '\0')
{
if (S[i] == T[j])
{
i++;
j++;
}
else
{
j = next[j]; //字符不等时,T串回退到next[j]位置。
if (j == -1)
{
i++;
j++;
}
}
}
if (T[j] == '\0')
{
return (i - strlen(T)) + 1; //返回T的第一个字符在S串中的第几个位置(非下标)
}
else
{
return 0;
}
}
int main()
{
char S[] = "ababcabccabcacbab";
char T[] = "abcac";
cout << KMP(S, T) << endl;
}