HDU - 4300 Clairewd’s message (kmp)

本文通过一道具体题目介绍KMP算法的应用。问题涉及字符串匹配,使用KMP算法找到密文和明文的正确分割点,并实现密文到明文的转换。

Clairewd’s message

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6891    Accepted Submission(s): 2594


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
 

 

Author
BUPT
 

 

Source
 

 

Recommend
zhuyuanchen520
 
题目大意:先给出一段a-z对应的密文,第二行再给出一段密文+部分明文,要求输出密文+明文
 
解题思路:碰到字符串匹配的问题首先想到的就是kmp。整体思路就是讲第二行的字符串全当成明文翻译成密文,这样得到的字符串就是一段无意义的+之前部分明文对应的密文。然后利用kmp进行匹配,统计部分明文的数量,然后翻译输出就可以了。(学长的思路,没看其它的解题报告,自己完完整整做的第一道kmp题目。。想想就刺激)
做的时候先是用map<char,char>来存储明文密文对应的关系,后来发现要么明文转换成密文麻烦,要么密文翻译成明文麻烦,所以用了两个map,m是明文->密文,m2是密文->明文。
(因为本人没啥基础。。刚刚设计算法这一类,可能有很多地方写的太麻烦。。下面贴代码)
 
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int maxn=1e5+5;
int Next[maxn];
char s[maxn],ss[maxn],a[maxn];
map<char,char> m,m2;

void getNext() //构建next数组,直接套模板
{
    int i=0,j=-1;
    Next[0] = 0;
    Next[1] = 0;
    int l = strlen(s);
    for(i=1;i<l;i++)
    {
        int j=Next[i];
        while(j&&s[j]!=s[i]) j=Next[j];
        if(s[i]==s[j])
        {
            Next[i+1] = j+1;
        }
        else
        {
            Next[i+1] = 0;
        }
    }
}

int kmp()
{
    getNext();
    int j = 0,i=0;
    int ll = strlen(ss);
    int l = strlen(s);
/*    for(int i=0;i<ll;i++)
    {
        printf("%c",ss[i]);
    }
    printf("\n");
    for(int i=0;i<l;i++)
    {
        printf("%c",s[i]);
    }
    printf("\n");
    for(int i=0;i<=l;i++)
    {
        printf("%d",Next[i]);
    }
    printf("\n");
*/    for(int i=0;i<ll;i++)
    {
        while(j&&s[j]!=ss[i]) j=Next[j];
        //printf("ss[%d]-%c s[%d]-%c\n",i,ss[i],j,s[j]);
        if(s[j]==ss[i])
        {
            j++;
        }
        if(i==ll-1) //匹配进行到最后一个,返回j,j即为原字符串中明文数量
        {
            //printf("%d\n",j);
            return j;
        }
    }
    return 0;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",a);
        scanf("%s",s);
        int l = strlen(a);
        for(int i=0;i<l;i++)
        {
            m['a'+i] = a[i];       //m[明文] = 密文
            m2[a[i]] = 'a'+i;      //m2[密文] = 明文
        }
        l = strlen(s);
        int k=0;
        for(int i=(l+1)/2;i<l;i++) //因为密文肯定完整,所以l的前半部分肯定是密文,不用转换
        {
            ss[k++] = m[s[i]];
        }
        ss[k] = '\0';
        int End = kmp();
        End = l-End;//前面密文与明文分割的标志
        for(int i=0;i<End;i++)
        {
            printf("%c",s[i]);
        }
        for(int i=0;i<End;i++)
        {
            printf("%c",m2[s[i]]);
        }
        printf("\n");
    }
}

 

转载于:https://www.cnblogs.com/WWkkk/p/7326676.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值