题目描述
Alice和Bob正在悄悄地给对方发信息,信息都是由英文小写字母组成的,他们约定,所有的字母都得经过一个字母表进行变换,以防泄漏。另一方面John却在监听。
John发现,Alice和Bob通信的时候,总是先发送加密后的密文,然后紧接着发送原文。
但是Alice和Bob似乎也意识到了似乎有人监听,有时候会随意中断了他们的通信。不过每次都是在发送完密文之后才停止传送的。也就是说,John截获到的信息是密文的全文以及前一部分原文。原文可能一个字符都没有,也可能原文的全文都被截获。
现在John比较头疼,他虽然已经得到了他们两个人通信的加密字母表,但是分不清楚什么地方是密文和明文的分界线。你能帮他还原回完整的传输内容吗?
如果有多种可能时,John认为那个最短的信息才是原始的。
输入
第一行是密码表格,包含26个小写字母,依次表示a-z加密后的字母。
第二行是John截获到的通信信息。
输出
包含一行,表示还原后的通信信息。
样例输入
abcdefghijklmnopqrstuvwxyzabcdab
样例输出
abcdabcd
提示
【样例输入2】
qwertyuiopasdfghjklzxcvbnm
qwertabcde
【样例输出2】
qwertabcde
【数据范围】
通信长度L<=100000。
【思路】裸KMP
<span style="font-size:18px;">#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100005;
int trs[maxn],nxt[maxn];
char tar[maxn];
inline void getnxt(char *a){
int len=strlen(a),s=(len+1)>>1;
int j=0;
for(int i=s;i<len;++i){
char ch=trs[a[j]];
if(j>0 && a[i]!=ch)j=nxt[j];
if(a[i]==ch)++j;
nxt[i+1]=j;
}
}
int main(){
memset(nxt,0,sizeof(nxt));
for(int i=1;i<=26;++i){
char c=getchar();
trs[c]=i+96;
}
scanf("%s",tar);
getnxt(tar);
int l=strlen(tar);
int n=l-nxt[l];
for(int i=0;i<n;++i)printf("%c",tar[i]);
for(int i=0;i<n;++i){
char c=trs[tar[i]];
printf("%c",c);
}
printf("\n");
return 0;
}</span>