题目大意:给定一个匹配串(长度为26)s,其中s[i]对应第i个小写字母,再给一段由密文和明文混杂的字符串(可能只有密文)
其中密文必定已全部给出,明文则不一定,现在要求对于给出的字符串所能得到的最短的完整的密文+明文串,
即密文和明文完全匹配。
题目分析:首先注意的是字符串最大长度为1e5,直接暴力枚举字符的复杂度是O(N^2)(但这题数据弱暴力也能水过去)
那么可以考虑用KMP进行匹配。首先分析题目可知密文串的长度必定大于或等于给出的字符串的总长度的一半,那么可以
先设置原串的一个副串,把原串中前一半的字符全部转为明串,进行KMP匹配后分析Next[len](len为字符串总长度),
根据Next[len]对副串进行相应的转换,最后得解。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
char ax[100000+5];
int f[100000+5];
char model[30],cha[1000];
void kmp()
{
int N=strlen(ax);
f[0]=f[1]=0;
for(int i=ceil(N*1.0/2);i<N;i++)//从一半开始匹配,消除前后字符相同的影响
{
int j=f[i];
while(j&&ax[i]!=ax[j])
j=f[j];
f[i+1]=ax[i]==ax[j]?j+1:0;
//cout<<f[i+1]<<endl;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
char bx[200000+5];
scanf("%s",&model);
scanf("%s",&ax);
int len=strlen(model);
for(int i=0;i<len;i++)
cha[model[i]]='a'+i;
len=strlen(ax);
for(int i=0;i<len;i++)
bx[i]=ax[i];
for(int i=0;i<ceil(len*1.0/2);i++)
ax[i]=cha[ax[i]];
kmp();
int t=f[len];
int n=len;
for(int k=t;k<len-t;k++)
bx[n++]=cha[bx[k]];
for(int i=0;i<n;i++)
printf("%c",bx[i]);
printf("\n");
}
return 0;
}