思路:extend[i]表示原串以第i開始与模式串的前缀的最长匹配。经过O(n)的枚举,我们能够得到,若extend[i]+i=len且i>=extend[i]时,表示t即为该点之前的串,c即为该点之前的str串,最后输出就可以。
#include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; const int N=100010; char s[N],t[N]; char c[N]; int next[N],extand[N]; void getNext(int lt) { next[0]=lt; int a=0; while(a<lt-1&&t[a+1]==t[a]) a++; next[1]=a; a=1; for(int k=2;k<lt;k++) { int p=a+next[a]-1; int L=next[k-a]; if(k-1+L>=p) { int j=(p-k+1)>0?(p-k+1):0; while(j+k<lt&&t[k+j]==t[0+j]) j++; next[k]=j; a=k; } else next[k]=L; } } void getExtand(int ls,int lt) { getNext(lt); int a=0; int minLen=min(ls,lt); while(a<minLen&&t[a]==c[a]) a++; extand[0]=a; a=0; for(int k=1;k<ls;k++) { int p=a+extand[a]-1; int L=next[k-a]; if(k-1+L>=p) { int j=(p-k+1)>0?(p-k+1):0; while(j+k<ls&&j<lt&&t[j+k]==c[j]) j++; extand[k]=j; a=k; } else extand[k]=L; } } int main() { int T; cin>>T; while(T--) { cin>>s>>t; map<char,char> mmap; int lt=strlen(t); int ls=strlen(s); for(int i=0;i<ls;i++) mmap[s[i]]='a'+i; for(int i=0;i<lt;i++) c[i]=mmap[t[i]]; getExtand(lt,lt); int i; for(i=0;i<lt;i++) { if(i+extand[i]>=lt&&i>=extand[i]) break; } for(int j=0;j<i;j++) cout<<t[j]; for(int j=0;j<i;j++) cout<<c[j]; cout<<endl; } return 0; }