HDU4300-Clairewd’s message-KMP

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

题目意思真的非常难读懂。

题意:给定两组字符串,第一组仅仅有26个字符表相应明文中a,b,c,d....z能够转换第一个,第二个...第26个字符变成密文,

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

           假设有多种明文则取最大的明文。

解题思路就是将前一半一定是密文的字符装换成明文。然后+后面的字符,从后往前匹配,匹配小于等于长度一半的最长前缀;

#include<map>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
#include<set>
#include<vector>
#include<algorithm>
#define LL long long
#define inf 1<<30
#define s(a) scanf("%d",&a)
#define CL(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=200005;
int n,m;
char a[N],b[N];
char num[N];
char c[N];
int nnext[N];
void get_nnext(char *a,int len)
{
    int j=-1,i=0;
    nnext[0]=-1;
    while(i<len){
        if(j == -1 || a[i] == a[j]) nnext[++i]=++j;
        else j=nnext[j];
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        cin>>a>>b;
        int len=strlen(b),k=len;
        for(int i=0;i<26;i++) num[a[i]-'a']='a'+i;
        for(int i=0;i<(len+1)/2;i++) c[i]=num[b[i]-'a'];    //  将前一部分转换成密文。
        for(int i=(len+1)/2;i<=len;i++) c[i]=b[i];          //  拼接后一部分明文;
        get_nnext(c,len);
        while(nnext[k]>len/2) k=nnext[k];         //  从后往前匹配;寻找长度小于len的最长前缀;
        cout<<b;
        for(int i=nnext[k];i<len-nnext[k];i++) cout<<num[b[i]-'a'];        //  输出还不够的字符串。须要注意点的是这里输出的解密的字符,而不能直接用c[i];
        cout<<endl;
    }
    return 0;
}


 

原文地址:https://www.cnblogs.com/wzzkaifa/p/6972875.html