详解链接
hdu4300
题解链接
next[i]: T[i]…T[m-1]与T的最长公共前缀长度;
extend[i]: S[i]…S[n-1]与T的最长公共前缀的长度。
为什么说这是KMP算法的扩展呢?显然,如果在S的某个位置i有extend[i]等于m,则可知在S中找到了匹配串T,并且匹配的首位置是i。而且,扩展KMP算法可以找到S中所有T的匹配。接下来具体介绍下这个算法。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
int Next[maxn],extend[maxn];
void get_next(char a[])
{
int len=strlen(a);
Next[0]=len;
int st,p;
for(int i=1,j=-1;i<len;i++,j--)
{
if(j<0||i+Next[i-st]>=p)
{
if(j<0)
p=i,j=0;
while(p<len&&a[p]==a[j])
p++,j++;
Next[i]=j;
st=i;
}
else
Next[i]=Next[i-st];
}
}
void get_extend(char a[],char b[])
{
memset(Next,0,sizeof(Next));
memset(extend,0,sizeof(extend));
get_next(b);
int st,p;
int lena=strlen(a),lenb=strlen(b);
for(int i=0,j=-1;i<lena;i++,j--)//j代表i与p 的距离
{
if(j<0||i+Next[i-st]>=p)//可以等于p
{
if(j<0)
p=i,j=0;
while(p<lena&&j<lenb&&a[p]==b[j])
p++,j++;
extend[i]=j;
st=i;
}
else
extend[i]=Next[i-st];
}
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
char s1[100],s2[100010],s3[200010],s4[100];
scanf("%s%s",s1,s2);
int len=strlen(s2);
for(int i=0;i<26;i++)
s4[s1[i]-'a']='a'+i;
for(int i=0;i<len;i++)
s3[i]=s1[s2[i]-'a'];
s3[len]='\0';
get_extend(s3,s2);
int f=len;
for(int i=(len+1)/2;i<len;i++)
{
if(extend[i]+i==len)
{
f=i;
break;
}
}
for(int i=0;i<f;i++)
printf("%c",s2[i]);
for(int i=0;i<f;i++)
printf("%c",s4[s2[i]-'a']);
printf("\n");
}
}