题目大意:
输入样例个数,每个样例有两行,第一行是26个字母,分别代表a~z加密后的密文;第二行代表一串密文+明文,密文一定是完整的,但明文可能不完整,让你输出最短的(密文+明文);
基本思路:
拓展kmp,因为密文是完整的,所以它的长度必然是一半以上,所以把前一半转换成明文放到另一个数组里,然后后半部分原封不动的放到该数组里,然后拓展kmp,求一下next,然后从一半以后一直往后找,找到的话,就跳出,然后基本把把问题解决了;
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 100000+10; int nx[maxn],ex[maxn]; char S[maxn],T[maxn]; char s1[maxn],a[27],b[27]; int lent,lens; void getNext(){ nx[0]=lent; int j=0; while(j+1<lent&&T[j]==T[j+1]) j++; nx[1]=j; int k=1; for(int i=2;i<lent;i++){ int p=k+nx[k]-1; int l=nx[i-k]; if(i+l<p+1) nx[i]=l; else{ j=max(0,p-i+1); while(i+j<lent&&T[i+j]==T[j]) j++; nx[i]=j; k=i; } } } /* void exkmp(){ int j=0; while(j<lens&&j<lent&&S[j]==T[j]) j++; ex[0]=j; int k=0; for(int i=1;i<lens;i++){ int p=k+nx[k]-1; int l=nx[i-k]; if(l+i<p+1) ex[i]=-l; else{ j=max(0,p-i+1); while(i+j<lens&&j<lent&&S[i+j]==T[j]) j++; ex[i]=j; k=i; } } } */ int main(){ int cas; scanf("%d",&cas); while(cas--){ scanf("%s%s",a,s1); for(int i=0;i<26;i++) b[a[i]-'a']=i+'a'; int len=strlen(s1); for(int i=0;i<(len+1)/2;i++) T[i]=b[s1[i]-'a']; for(int k=(len+1)/2;k<=len;k++) T[k]=s1[k]; lent=strlen(T); getNext(); int k; for(k=(len+1)/2;k<len;k++){ if(nx[k]==len-k) break; } printf("%s",s1); for(int i=len-k;i<k;i++) printf("%c",b[s1[i]-'a']); printf(" "); } return 0; }