题目链接:
HDU - 4300
题意分析:
单独抽出来一段很重要的话:
But GFW knows that Clairewd would always firstly send the ciphertext and then plaintext(Note that they
won't overlap each other). But he doesn't know how to separate the text because he has no idea about the whole message.
这一段话的意思是:
但是GFW知道Clairewd总是首先发送密文然后发送明文(注意它们不会相互重叠)。但他不知道如何分开文本,因为他不知道整个信息。
也就是说,题目中给出的这一块的数据是由密文和明文组成的!
题目的大致意思就是给出两个字符串,第一个字符串代表密匙,第二个字符串代表由密文和明文组成的串(密文是给出来所有了,但是明文有可能给出一部分,也有可能没有),所以现在我们要先把第二个串按照密文得出一个新字符串,判断这个字符串的密文通过密匙得到的原文是否与原明文相同(有点绕,下面给出一张图),并且把这个串给输出出来。
题解:
现在就拿图中第二个样例来说,如果按照给出的密文对应法则,可以得到这个串所对应的串abcdekxvmc。
我们发现,得到得这个串的前一半刚好和原本串的后一部分相同,注意,原本串的后一部分叫做明文,而密文对应的是明文,所以这种情况可以直接输出。
现在把这个串给改变一下:
把原本的t改成了y,那么它所对应的字母就相应的变成了f,我们观察到abcde不等于abcdf,也就是说原本的这个串里面全是密文,没有一个是明文!!!!!
现在我们再想一下,如果说上面串的后缀中与下面串的前缀中有相同的呢?
这个图是我为了演示随便给出的一个例子,可以看出,我们可以直接把上面的串给输出,然后再打印后面的字符(后面的字符代表原文,刚好是下面的)
打印的位置应该从 next[] 开始,结束的位置是 总长- next[]
也就是说我们只需要打印图中的1区域即可!
AC代码:
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<string>
#include<iostream>
using namespace std;
const int maxn=1e5+10;
int N,nexxt[maxn];
char num1[maxn],num2[maxn];
int num_long2;
int ex_num1[maxn];
char ex_num2[maxn];
void find_next()
{
nexxt[0]=-1;
int k=-1;
int j=0;
while(j<num_long2)
{
if(k==-1||ex_num2[k]==ex_num2[j])
{
++k;
++j;
if(ex_num2[k]!=ex_num2[j])
{
nexxt[j]=k;
}
else
{
nexxt[j]=nexxt[k];
}
}
else
{
k=nexxt[k];
}
}
}
int print_next()
{
int i,j=0;
if(num_long2%2==1)
{
i=num_long2/2+1;
}
else
{
i=num_long2/2;
}
while(i<num_long2&&j<num_long2)
{
if(j==-1||num2[i]==ex_num2[j])
{
++i;
++j;
}
else
{
j=nexxt[j];
}
}
return j;
}
int main()
{
cin>>N;
while(N--)
{
scanf("%s %s",num1,num2);
//其中num代表的是对应规则
for(int i=0;i<26;++i)
{
char word=num1[i];
ex_num1[word]=i;
//每个字母对应的数字
}
//找到了对应规则,进行第二步计算,变换
num_long2=strlen(num2);
for(int i=0;i<num_long2;++i)
{
ex_num2[i]='a'+ex_num1[num2[i]];
}
//变换完毕,进行计算前后缀长度
find_next();
//找到next数组之后,进行判断。
int longg=print_next();
if(longg*2==num_long2)
{
printf("%s\n",num2);
}
else
{
printf("%s",num2);
int number=num_long2-longg;
for(int i=longg;i<number;++i)
{
printf("%c",ex_num2[i]);
}
printf("\n");
}
}
return 0;
}