题意
给你一个密文转化为明文的规则:
qwertyuiopasdfghjklzxcvbnm
a对应q,b对应w,,,,
现在我们知道一个字符串A这个字符串是由一个密文+一个明文组成的,并且可能不完整,问你这个字符串的最短长度是多少
思路
既然是由密文与明文组成的,那么至少 i>=len(A)/2长度开始判断,对于当前位置的i来说,<i的部位是密文,>=i的部分为明文,
如果<i的部分通过转换规则转化为>=i的部分,那么这里就是分界点,所以我们就要判断>=i的部分是不是与<i的部分相等,!!!这不就是后缀与前缀的匹配嘛,或者为从i开始的与从0开始的最大前缀长度,正是扩展KMP,所以我们将A字符串全部当作为密文通过转化为明文B,以A为模板串,B为匹配串,进行扩展KMP
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
#define MAXNUM 1000050
char s1[2*MAXNUM], s2[2*MAXNUM];//s2为待匹配字符串
int s1size, s2size;
//num[i]保存s2长度为i的前缀子串在s1中出现的数目,非必需
int num[2*MAXNUM];
//extend为s1串中对应位置开始匹配的最大前缀长度
//snext为s2串中[i,len]与s2的最长公共前缀长度
int snext[2*MAXNUM],extend[2*MAXNUM];
void getextnext()
{
int i, length = s2size;
snext[0] = length;
for (i = 0; i<length - 1 && s2[i] == s2[i + 1]; i++);
snext[1] = i;
int a = 1;
for (int k = 2; k < length; k++)
{
int p = a + snext[a] - 1, L = snext[k - a];
if ((k - 1) + L >= p)
{
int j = (p - k + 1)>0 ? (p - k + 1) : 0;
while (k + j<length && s2[k + j] == s2[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
snext[k] = j, a = k;
}
else snext[k] = L;
}
}
void kmpextend()
{
s1size = strlen(s1), s2size = strlen(s2);
getextnext();
int a = 0;
int MinLen = s1size>s2size ? s2size : s1size;
while (a<MinLen && s1[a] == s2[a]) a++;
extend[0] = a, a = 0;
for (int i = 1; i < s1size; i++)
{
int p = a + extend[a] - 1, L = snext[i - a];
if ((i - 1) + L >= p)
{
int j = (p -i + 1)>0 ? (p - i + 1) : 0;
while (i + j<s1size && j<s2size && s1[i + j] == s2[j])
j++;
extend[i] = j;
a = i;
}
else extend[i] = L;
}
//计算Num,可去
for (int i = 0; i < s1size; i++)
num[extend[i]]++;
for (int i = s2size - 1; i >= 1; i--)
num[i] += num[i + 1];
}
int XHJ(char str[])
{
// 已经求出next数组
int kk; // kk保存最短循环节
int len=strlen(str);
for(int i=1; i<=len; ++i)
{
if(i+snext[i]>=len){
kk = len%i ? len : i;
break;
}
}
return kk;
}
map<char,char> mp;
char str1[MAXNUM];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
mp.clear();
scanf("%s%s",str1,s1);
int len1=strlen(str1);
for(int i=0;i<len1;i++)
mp[str1[i]]=i+'a';
int len2=strlen(s1);
for(int i=0;i<len2;i++) s2[i]=mp[s1[i]];
kmpextend();
int ans=len2;
for(int i=len2/2;i<len2;i++)
{
if(extend[i]+i>=len2&&(2*i)>=len2)
{
ans=i;break;
}
}
for(int i=0;i<ans;i++) printf("%c",s1[i]);
for(int i=0;i<ans;i++) printf("%c",mp[s1[i]]);
cout<<endl;
}
return 0;
}