hdu 4300 Clairewd’s message(详解,扩展KMP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300

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

2012 Multi-University Training Contest 1

题意:

比较难理解,给定两组字符串,第一组只有26个字符表对应明文中a,b,c,d....z可以转换第1个,第2个...第26个字符变成密文,

第二组字符串是给定的密文+明文,明文可能不完整(缺失或没有),叫你补充完整整个密文+明文是最短的;

PS:读了好几篇都不理解题意,用了翻译工具还是不能理解,最后还是百度了才知道题意!(毕竟英语太渣);

思路:

把给出的不完整的明文加密文字符串全部转换一次,将转换后的做模式串,与原串进行kmp,记录返回的j值(j值代表的就是前缀和后缀的最长相等长度),然后再与给出的明文加密文字符串比较一下。

代码如下:

//#pragma warning (disable:4786)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <climits>
#include <ctype.h>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <deque>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps=1e-9;
const double pi=3.1415926535897932384626;
#define INF 1e18
//typedef long long LL;
//typedef __int64 LL;
const int MAXN = 100017;

char strm[MAXN];//密码表
char strz[MAXN];//不完整的密文和密文
char str[MAXN]; //密码表转换后
char s[MAXN];   //密文和明文转换后
int next[MAXN];

void getnext( char T[], int len)
{
    int i = 0, j = -1;
    next[0] = -1;
    while(i < len)
    {
        if(j == -1 || T[i] == T[j])
        {
            i++, j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
}
int KMP(int len1, int len2)
{
    int i, j = 0;
    if(len1%2 == 1)
    {
        i = len1/2+1;
    }
    else
        i = len1/2;
    while(i < len1 && j < len2)
    {
        if(j == -1 || strz[i] == s[j])
        {
            i++, j++;
        }
        else
            j = next[j];
    }
    return j;//j值代表的就是前缀和后缀的最长相等长度
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",strm);
        for(int i = 0; i < 26; i++)
        {
            char ss = strm[i];
            str[ss] = i;
        }
        scanf("%s",strz);
        int lenz = strlen(strz);
        for(int i = 0; i < lenz; i++)//将密文和明文按照密码表转换
        {
            int tt = str[strz[i]];
            s[i] = 'a' + tt;
        }
        int lens = strlen(s);
        getnext(s, lens);
        int j = KMP(lenz, lens);//得到密文的个数
        if(j*2 == lenz)//前缀和后缀恰各占一半
        {
            printf("%s\n",strz);
        }
        else
        {
            int tt = lenz - j;
            printf("%s",strz);
            for(int i = j; i < tt; i++)//需要添加的明文
            {
                printf("%c",s[i]);
            }
            printf("\n");
        }
    }
    return 0;
}
时间: 2024-11-05 12:15:57

hdu 4300 Clairewd’s message(详解,扩展KMP)的相关文章

hdu 4300 Clairewd’s message (KMP)

给定一个翻译表,即第i个字母用哪个字母表示 再给一个串,里面前面为密文,后面为明文,密文一定是完整的,但明文不完整或可能没有 求这个完整的前面密文后面明文的串 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; int next[100010]; char a1[100010],a2[100010],a3[100010]; void Ge

HDU 4300 Clairewd&#39;s message ( 拓展KMP )

题意 : 给你一个包含26个小写字母的明文密文转换信息字符串str,第一个表示'a'对应的密文是str[0].'b'对应str[1]--以此类推.接下来一行给你一个另一个字符串,这个字符串由密文+明文组成,但是现在后面部分的明问可能有不完整的情况(也有可能缺失只包含密文),问你现在最少需要补充多多少个字符串才能使得字符串变成完整的满足==>密文+密文对应的明文 组成的字符串,将这个完整的字符串输出出来. 分析 : 冷静分析一下可以发现,在给出的残缺字符串中,前面的一半肯定是属于密文的!如果不是这

HDU 4300 Clairewd‘s message 拓展KMP入门

HDU 4300 Clairewd's message 拓展KMP入门 题意 原题链接 这个题关键是要读懂题意,我做的时候就没有读懂,泪.题意是说给你的一个两个字符串,一个是26个字母密码表,依次对应替换的字母.然后给你一个字符串,这个字符串是不完整的(完整的应该是前半部分是加密的,后半部分是解密了的),然而,给你的字符串一定是加密的部分+一部分解密的部分(可以是全部,也可以是没有),让你求出最短的完整字符串,包括密文和明文: 解题思路 考虑给出的字符串S加密部分一定全部给出,所以给出的字符串的

hdu 4300 Clairewd’s message(kmp/扩展kmp)

题意:真难懂.. 给出26个英文字母的加密表,明文中的'a'会转为加密表中的第一个字母,'b'转为第二个,...依次类推. 然后第二行是一个字符串(str1),形式是密文+明文,其中密文一定完整,而明文可能不完整(也可能没有). 求出最短的完整的字符串(密文+明文). 思路: 1.用kmp来做: 首先肯定的是,给定的串中明文长度一定小于等于密文.也就是说明文长度小于等于总长的一半. 于是,取总长的后一半作为主串,然后把串反翻译一遍得到str2,然后用str2与str1的后一半进行匹配.首次把st

hdu 4300 Clairewd’s message 字符串哈希

Clairewd’s message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10376    Accepted Submission(s): 3709 Problem Description Clairewd is a member of FBI. After several years concealing in BUPT,

HDU 4300 Clairewd’s message(初遇拓展KMP)

昨晚一不小心学了拓展KMP,被虐了一晚,最终是这份资料救了我...http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 说得简单易懂. 然后学了kuangbin的模版: /* * 扩展KMP算法 */ //next[i]:x[i...m-1]与x[0...m-1]的最长公共前缀 //extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀 void pre_EKMP(char x[],int m,int next[

HDU 4300 Clairewd’s message(扩展KMP)

思路:extend[i]表示原串以第i开始与模式串的前缀的最长匹配.经过O(n)的枚举,我们可以得到,若extend[i]+i=len且i>=extend[i]时,表示t即为该点之前的串,c即为该点之前的str串,最后输出即可. #include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; const int N=100010; char

HDU 4300 Clairewd’s message

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 a

HDU 3613 Best Reward 正反两次扩展KMP

题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考虑扩展KMP 输出a串 得到a的反串b 求出f[0]和f[1] 和 extend[0]和extend[1] 正反求2次 枚举位置i 分成2部分0到i-1 和i到n-1 由于分成的2部分必须组成原字符串 就是不能多也不能少 那么推断i+extend[i]是否等于n 等于说明i到n-1这个部分是回文串