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

题意:真难懂。。

给出26个英文字母的加密表,明文中的‘a‘会转为加密表中的第一个字母,‘b‘转为第二个,...依次类推。

然后第二行是一个字符串(str1),形式是密文+明文,其中密文一定完整,而明文可能不完整(也可能没有)。

求出最短的完整的字符串(密文+明文)。

思路:

1.用kmp来做:

首先肯定的是,给定的串中明文长度一定小于等于密文。也就是说明文长度小于等于总长的一半。

于是,取总长的后一半作为主串,然后把串反翻译一遍得到str2,然后用str2与str1的后一半进行匹配。首次把str1的后一半匹配完的位置即是给定的串中明文开始的位置。

因为是首次,所以保证了前面的密文长度最小,即总长度最小。

然后输出密文+明文,即可。

2.用扩展kmp来做:

kmp:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define MaxSize 100005

int _next[MaxSize];

void GetNext(char t[]){//求next数组
    int j,k,len;
    j=0;
    k=-1;
    _next[0]=-1;
    len=strlen(t);
    while(j<len){
        if(k==-1||t[j]==t[k]){
            ++j;
            ++k;
            _next[j]=k;//此句可由优化替代
            /*优化(仅保证求KMPIndex时可用。谨慎使用。)
            if(t[j]!=t[k])next[j]=k;
            else next[j]=next[k];
            */
        }
        else k=_next[k];
    }
}

int KMPIndex(char s[],char t[]){//求子串首次出现在主串中的位置
    int i,j,lens,lent;
    i=j=0;
    lens=strlen(s);
    lent=strlen(t);

    while(i<lens&&j<lent){
        if(j==-1||s[i]==t[j]){
            ++i;
            ++j;
        }
        else j=_next[j];
    }
    //if(j>=lent)return i-lent;
    //else return -1;
    return j;
}

int main(){
    char str[27],str1[MaxSize],str2[MaxSize];
    char cstr[27];//密文->明文
    int t,i,len1,len11,num;
    scanf("%d",&t);

    while(t--){
        scanf("%s%s",str,str1);
        for(i=0;i<26;++i)
            cstr[str[i]-‘a‘]=‘a‘+i;
        len1=strlen(str1);//
        for(i=0;i<len1;++i)
            str2[i]=cstr[str1[i]-‘a‘];
        str2[i]=‘\0‘;
        GetNext(str2);//求子串的next数组
        len11=len1/2;//假设密文(明文)长度
        num=KMPIndex(str1+len1-len11,str2);//串中的明文个数
        printf("%s",str1);
        len11=len1-num;//实际密文(明文)长度
        for(i=num;i<len11;++i){
            printf("%c",str2[i]);
        }
        printf("\n");
    }
    return 0;
}

扩展kmp:

时间: 2024-10-14 00:19:54

hdu 4300 Clairewd’s message(kmp/扩展kmp)的相关文章

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(初遇拓展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)

给定一个翻译表,即第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 字符串哈希

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)

题目链接: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 ea

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

KMP &amp; 扩展KMP &amp; Manacher 专题

KMP & 扩展KMP & Manacher  专题 先来模版: void getNext(int *b,int m) { Next[0]=-1; int i=0,j=-1; while(i<m&&j<m){ if(j==-1||b[i]==b[j]) Next[++i]=++j; else j=Next[j]; } } int kmp(int *a,int *b,int n,int m) { getNext(b,m); int i=0,j=0; while(i