扩展KMP解决的经典问题:定义母串S和子串T,求T与S的每一个后缀的最长公共前缀。应用到此题将s1作为子串,s2作为母串进行扩展KMP求解,取最长的公共前缀且在s2中为后缀的答案。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void pre_eKmp(char s[],int nt[])
{
int m = strlen(s);
nt[0] = m;
int j = 0;
while(j + 1 < m && s[j] == s[j + 1])
j++;
nt[1] = j;
int k = 1;
for(int i = 2;i < m; i++)
{
int p = nt[k] + k - 1;
int l = nt[i - k];
if(i + l < p + 1)
nt[i] = l;
else
{
j = max(0,p - i + 1);
while(i + j < m && s[i + j] == s[j])
j++;
nt[i] = j;
k = i;
}
}
}
void eKmp(char x[],int xlen,char y[],int ylen,int nt[],int extend[])
{
pre_eKmp(x,nt);
int j = 0;
while(j < ylen && j < xlen && x[j] == y[j])
j++;
extend[0] = j;
int k = 0;
for(int i = 1;i < ylen; i++)
{
int p = extend[k] + k - 1;
int l = nt[i - k];
if(i + l < p + 1)
extend[i] = l;
else
{
j = max(0,p - i + 1);
while(i + j < ylen && j < xlen && y[i + j] == x[j])
j++;
extend[i] = j;
k = i;
}
}
}
int main()
{
char s[100050],t[100050];
int nt[100050],extend[100050];
memset(extend,0, sizeof(extend));
memset(nt,0, sizeof(nt));
while(scanf("%s %s",s,t) == 2)
{
eKmp(s,strlen(s),t,strlen(t),nt,extend);
int ans = 0;
for(int i = strlen(t) - 1,j = 0;j < strlen(s); j++, i--)
{
if(extend[i] == strlen(t) - i)
ans = max(ans,extend[i]);
}
if(ans)
{
for(int i =0;i < ans; i++)
printf("%c",s[i]);
printf(" ");
}
printf("%d\n",ans);
}
return 0;
}