KMP博客:https://www.cnblogs.com/SYCstudio/p/7194315.html
注:pre数组中保存的是该最长前后缀的前缀结束下标(字符串从0开始),如果要求最长相同前缀后缀的长度,要输出pre[i]+1。
获取next函数
void get_pre()
{
pre[0] = -1;
for(ll i = 1; i < len2; i++)
{
ll j = pre[i-1];
while( j >= 0 && s2[i] != s2[j+1] )
{
j = pre[j];
}
if(s2[i] == s2[j+1])
pre[i] = j+1;
else
pre[i] = -1;
}
return ;
}
kmp匹配
void kmp()
{
ll i = 0, j = 0;
while(i < len1)
{
if(s1[i] == s2[j])
{
i++;
j++;
if(j == len2)
{
cout << i - len2 + 1 << endl;
j = pre[j-1]+1;
}
}
else
{
if(j == 0)
i++;
else
j = pre[j-1]+1;
}
}
return ;
}
exkmp博客:https://blog.csdn.net/dyx404514/article/details/41831947
定义母串S,和字串T,设S的长度为n,T的长度为m,求T与S的每一个后缀的最长公共前缀
设extend数组,extend[i]表示模式串与文本串[i,n-1]的最长公共前缀,要求出所有extend[i](0<=i<n)。
数组pre(next)[i]表示模式串[i,m-1]和模式串的最长公共前缀长度
void get_next(char str[])
{
int i=0,j,po,len=strlen(str);
pre[0]=len;//初始化pre[0]
while(str[i]==str[i+1]&&i+1<len)//计算pre[1]
i++;
pre[1]=i;
po=1;//初始化po的位置
for(i=2;i<len;i++)
{
if(pre[i-po]+i<pre[po]+po)//第一种情况,可以直接得到pre[i]的值
pre[i]=pre[i-po];
else//第二种情况,要继续匹配才能得到pre[i]的值
{
j=pre[po]+po-i;
if(j<0)j=0;//如果i>po+pre[po],则要从头开始匹配
while(i+j<len&&str[j]==str[j+i])//计算pre[i]
j++;
pre[i]=j;
po=i;//更新po的位置
}
}
return ;
}
void exkmp(char str1[],char str2[])
{
int i=0,j,po,len=strlen(str1),l2=strlen(str2);
get_next(str2);//计算子串的next数组
while(str1[i]==str2[i]&&i<l2&&i<len)//计算ex[0]
i++;
extend[0]=i;
po=0;//初始化po的位置
for(i=1;i<len;i++)
{
if(pre[i-po]+i<extend[po]+po)//第一种情况,直接可以得到ex[i]的值
extend[i]=pre[i-po];
else//第二种情况,要继续匹配才能得到extend[i]的值
{
j=extend[po]+po-i;
if(j<0)j=0;//如果i>extend[po]+po则要从头开始匹配
while(i+j<len&&j<l2&&str1[j+i]==str2[j])//计算extend[i]
j++;
extend[i]=j;
po=i;//更新po的位置
}
}
return ;
}
以及队友的EXKMP板子
int Next[MAXN], extand[MAXN];
char s[MAXN], a[MAXN];
void getNext(char *T)
{// Next[i]: 以第i位置开始的子串 与 T的公共前缀
int i, length = strlen(T);
Next[0] = length;
for(i = 0; i < length - 1 && T[i] == T[i+1]; i++);
Next[1] = i;
int a = 1;
for(int k = 2; k < length; k++)
{
int p = a+Next[a]-1, L = Next[k-a];
if((k - 1) + L >= p )
{
int j = (p - k + 1) > 0 ? (p - k + 1) : 0;
while(k + j < length && T[k + j] == T[j])
j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
Next[k] = j, a = k;
}
else
Next[k] = L;
}
}
void getextand(char *S,char *T)
{
memset(Next,0,sizeof(Next));
getNext(T);
int Slen = strlen(S), Tlen = strlen(T), a = 0;
int MinLen = Slen > Tlen ? Tlen : Slen;
while(a < MinLen && S[a] == T[a]) a++;
extand[0] = a, a = 0;
for(int k = 1; k < Slen; k++)
{
int p = a + extand[a] - 1, L = Next[k-a];
if((k - 1) + L >= p )
{
int j = (p - k + 1) > 0 ? (p - k + 1) : 0;
while(k + j < Slen && j < Tlen && S[k + j] == T[j]) j++;
extand[k] = j; a = k;
}
else extand[k] = L;
}
}