输入规则
然后密文+半截明文
求出在哪里中间断开并且使得求出的密文要最短
算法:
拓展kmp,可以将原来的字符串全部回转成明文
也就是变成 明文+(明文的明文)
然后密文+半截明文
求出在哪里中间断开并且使得求出的密文要最短
算法:
拓展kmp,可以将原来的字符串全部回转成明文
也就是变成 明文+(明文的明文)
然后再拓展KMP就行
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e5;
int Next[maxn+100],extend[maxn+100];
char str1[maxn+100],str2[maxn+100],rule[30],rule_ver[30];
void GetNext(char *str);
void ExKMP(char *s1,char *s2);
int main()
{
int t,len,ed;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",rule,str1);
len=strlen(str1);
ed=len;
for(int i=0; i<26; i++)
rule_ver[rule[i]-'a']=i+'a';
for(int i=0; i<len; i++)
str2[i]=rule_ver[str1[i]-'a'];
ExKMP(str1,str2);
for(int i=(len+1)/2; i<len; i++)
if(extend[i]==len-i)
{
ed=i;
break;
}
for(int i=0; i<ed; i++)
printf("%c",str1[i]);
for(int i=0; i<ed; i++)
printf("%c",str2[i]);
printf("\n");
}
return 0;
}
void GetNext(char *str)
{
int i=0,j,pos,len=strlen(str);
Next[0]=len; //初始化next[0]
while(i+1<len&&str[i]==str[i+1]) i++; //初始化next[1]
Next[1]=i;
pos=1; //初始化pos
for(i=2; i<len; i++)
{
if(i+Next[i-pos]<pos+Next[pos])
Next[i]=Next[i-pos];
else
{
j=pos+Next[pos]-i;
if(j<0) j=0; //如果i>pos+next[pos],则从头开始
while(i+j<len&&str[i+j]==str[j]) j++;
Next[i]=j;
pos=i;
}
}
}
void ExKMP(char *s1,char *s2) //s2的后缀和s1的最长前缀
{
int i=0,j,pos,len1=strlen(s1),len2=strlen(s2);
GetNext(s2);
while(i<len1&&i<len2&&s1[i]==s2[i]) i++;
extend[0]=i;
pos=0;
for(int i=1; i<len1; i++)
{
if(i+Next[i-pos]<pos+extend[pos])
extend[i]=Next[i-pos];
else
{
j=pos+extend[pos]-i;
if(j<0) j=0;
while(i+j<len1&&j<len2&&s1[i+j]==s2[j]) j++;
extend[i]=j;
pos=i;
}
}
}