一道KMP的变式
本题仍是求最大前缀后缀,所以仍用KMP,但不同的是,本题有一个密码转换规则,不过好在题目中说了两段不重合,那么我们就可以在中间插入一个特殊符号'*'',保证求next数组时不会越过中线,然后把前半段按对应关系转化成明文,求next数组就行,本题难点在于边界条件的处理。
尽可能向已知或模板靠拢
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAXN=100000+7;
int init(){int rv=0,fh=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-') fh=-1;c=getchar();}while(c>='0'&&c<='9'){rv=(rv<<1)+(rv<<3)+c-'0';c=getchar();}return fh*rv;
}
int T,nxt[MAXN],nxt1[MAXN];
char table[400],s[MAXN],ys[400];
void getnxt(){nxt1[0]=-1;int len=strlen(s);int k=-1,j=0;while(j<len){if(k==-1||s[j]==s[k]) nxt1[++j]=++k;else k=nxt1[k];}
}
int main(){freopen("in.txt","r",stdin);T=init();while(T--){for(int i=1;i<=26;i++){scanf(" %c ",&table[i]);ys[table[i]-'a'+1]=i+'a'-1;}scanf("%s",s);int len=strlen(s);s[len]='*';s[++len]='\0';for(int i=len-1;i>len/2;i--){int t=s[i];s[i]=s[i-1];s[i-1]=t;}for(int i=0;i<=len/2-1;i++){printf("%c",s[i]);s[i]=ys[s[i]-'a'+1];}getnxt();int ans=len-nxt1[len];//cout<<s[ans-1]<<endl;if(!(len%2==0&&ans==len/2)){for(int i=len/2+1;i<=ans-1;i++) printf("%c",s[i]);for(int i=0;i<=ans-1;i++) if(i<len/2) printf("%c",s[i]);else if(i>len/2) printf("%c",ys[s[i]-'a'+1]);}else for(int i=0;i<=len/2-1;i++) printf("%c",s[i]);printf("\n");}fclose(stdin);return 0;
}