HDU 4300(KMP)

Problem Description
Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important messages and she was preparing for sending it to ykwd. They had agreed that each letter of these messages would be transfered to another one according to a conversion table.
Unfortunately, GFW(someone's name, not what you just think about) has detected their action. He also got their conversion table by some unknown methods before. Clairewd was so clever and vigilant that when she realized that somebody was monitoring their action, she just stopped transmitting messages.
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. However, he thinks that recovering the shortest possible text is not a hard task for you.
Now GFW will give you the intercepted text and the conversion table. You should help him work out this problem.
 

Input
The first line contains only one integer T, which is the number of test cases.
Each test case contains two lines. The first line of each test case is the conversion table S. S[i] is the ith latin letter's cryptographic letter. The second line is the intercepted text which has n letters that you should recover. It is possible that the text is complete.
Hint
Range of test data:
T<= 100 ;
n<= 100000;
 

Output
For each test case, output one line contains the shorest possible complete text.
 

Sample Input
  
  
2 abcdefghijklmnopqrstuvwxyz abcdab qwertyuiopasdfghjklzxcvbnm qwertabcde
 

Sample Output
  
  
abcdabcd qwertabcde



大致题意:大致是一个联邦调查员截获了一段重要信息,但是由于对方察觉,于是获取的信息是残缺的,但是已知其中密文是完整的,明文可能有缺失,现在要求你补全明文然后输出密文和明文。

输入:每组的测试数据分为两个字符串,第一个字符串为长度为26的翻译表,分别表示从a到z可以翻译成什么字符。

第二个字符串为待补全的信息,密文在前面部分,明文在后面,但是明文可能有缺失,也即是说有可能全是密文。


解题思路:假如这段信息为s1,先把这一段信息全部翻译成明文,翻译后的信息为s2,那么相等的最长s2前缀和s1后缀即是明文的长度。于是便可以将s1和s2合并在一个字符串,再利用求字符串最长相等前后缀的方法求出明文的长度。


具体代码如下:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn=1e5+100;

char str[maxn*2],s[28],s1[28]; //把翻译前后的字符串都存在str内,所以开了两倍的空间
int _next[maxn*2];

void Next(int len)
{
    int i=-1,j=0;
    _next[0]=-1;
    while(j<len)
    {
        if(i==-1||str[i]==str[j])
        {
            ++i,++j;
            _next[j]=i;
        }
        else i=_next[i];  //next不解释
    }
    return ;
}

int main()
{
    int i,t,len,num,answer;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);  //s表示明文翻译成密文的翻译表
        scanf("%s",str);
        for(i=0; i<26; i++)
            s1[s[i]-'a']=i+'a';   //s1表示密文翻译成明文的翻译表,后面需要通过密文反翻译成明文。
        len=strlen(str);
        printf("%s",str);  //因为只是明文可能有缺失,所以先把当前的信息输出,后面只需要求出缺失的信息。
        for(i=len; i<len+len; i++)
        {
            str[i]=s[str[i-len]-'a'];  //在str后面把翻译后字符串的赋进去。
        }
        str[i]='\0';
        Next(len+len);
        num=_next[len+len-1];
        answer=0;
        while(num!=-1)  //求出最长的相等前后缀
        {
            if(str[num]==str[len+len-1]&&num<len/2)  //因为密文肯定是完整的,所以明文的长度不可能超过字符串的一半。
            {
                answer=num+1;
                break;  //要求补全的信息最短,所以找到最长的就跳出。
            }
            num=_next[num];
        }
        for(i=answer; i<len-answer; i++)
            printf("%c",s1[str[i]-'a']);  //通过反翻译输出缺失的信息
        printf("\n");
    }
    return 0;
}



  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值