这道题问的就是将1个串如何变为stringA+stringB的形式,使得stringA是stringB经过映射得到相同的串。映射那步其实没有什么 价值,假设str为原串s经过映射后得到的串,我们可以以str为模式串,以s为原串做一次扩展KMP,得到extend数组,extend[i]表示原 串以第i开始与模式串的前缀的最长匹配。经过O(n)的枚举,我们可以得到,若extend[i]+i=len且i>=extend[i]时,表示 stringB即为该点之前的串,stringA即为该点之前的str串,最后输出即可。
#include<stdio.h>
#include<string.h>
#include<map>
#define maxn 200000
using namespace std;
map<char,char>map1;
int max(int x,int y)
{
return x>y?x:y;
}
char s[maxn],tab[maxn],c[maxn];
int next[maxn],extend[maxn];
void EKMP(char s[],char t[])//s[]为主串,t[]为模版串
{
int i,j,p,l;
int len=strlen(t);
int len1=strlen(s);
memset(next,0,sizeof(next));
memset(extend,0,sizeof(extend));
next[0]=len;
j=0;
while(1+j<len&&t[j]==t[1+j])j++;
next[1]=j;
int a=1;
for(i=2;i<len;i++)
{
p=next[a]+a-1;
l=next[i-a];
if(i+l<p+1)next[i]=l;
else
{
j=max(0,p-i+1);
while(i+j<len&&t[i+j]==t[0+j])j++;
next[i]=j;
a=i;
}
}
j=0;
while(j<len1&&j<len&&s[j]==t[j])j++;
extend[0]=j;
a=0;
for(i=1;i<len1;i++)
{
p=extend[a]+a-1;
l=next[i-a];
if(l+i<p+1)extend[i]=next[i-a];
else
{
j=max(0,p-i+1);
while(i+j<len1&&j<len&&s[i+j]==t[j])j++;
extend[i]=j;
a=i;
}
}
}
int main()
{
int i,j;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",tab,s);
int len=strlen(tab);
int len1=strlen(s);
for(i=0;i<len;i++)
{
map1[tab[i]]='a'+i;
}
for(i=0;i<len1;i++)
{
c[i]=map1[s[i]];
}
c[i]='\0';
EKMP(s,c);
for(i=0;i<len1;i++)
{
if(i+extend[i]>=len1&&i>=extend[i])
{
break;
}
}
for(j=0;j<i;j++)printf("%c",s[j]);
for(j=0;j<i;j++)printf("%c",map1[s[j]]);
printf("\n");
}
}