一道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]=' ';
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("
");
}
fclose(stdin);
return 0;
}