hdu4300 KMP

来源:互联网 发布:mysql语法大全 编辑:程序博客网 时间:2024/05/21 23:00

    题意:给你两个字符串S1,S1,其中S1[i]表示第i个字母对应的密码,S2由两部分构成,前面为暗文,后面为明文,题目保证暗文部分是完整的,但名文部分不一定完整(可以没有)。题目要求根据完整的暗文来找到明文,且要求补充后的S2总长度最短。

    刚开始想到的是枚举明文和暗文的分割线位置,写了一个程序后,果断超时。。。后来想到可以以原始串S2为主串,根据S1得到的S2'为模式串进行匹配,求出当i=len-1时,j的值,此时j可以理解为S2进行自身匹配时得到的next[len]的值。做到这里其实还没结束,比如对于第一个样例,最后匹配后得到的j=6,这个显然不符合题意,因为此时明文和暗文重合了。所以我们进行一次KMP后,需要判断j*2<=len,若不成立,则执行j=next[j],直到符合j*2<=len为止。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N=100005;int next[N],n;char A[N],B[N];//A串为原始串,B串为A串解密后的串void getnext(){    int i,j;    for(i=1,j=0;i<n;i++)    {        while(j>0&&B[i]!=B[j])            j=next[j-1];        if(B[i]==B[j])            j++;        next[i]=j;    }}void KMP(){    int i,j;    for(i=0,j=0;i<n;i++)    {        while(j>0&&A[i]!=B[j])            j=next[j-1];        if(A[i]==B[j])            j++;    }    //匹配长度的两倍不能大于n,    //否则明文和暗文就有重叠部分,不符合题意    while(j*2>n)        j=next[j-1];    //output    printf("%s",A);    for(i=j;i<n-j;i++)        putchar(B[i]);    putchar('\n');}int main(){    int t,i;    char hash[200];    cin>>t;    while(t--)    {        scanf("%s%s",hash,A);        for(i=0;i<26;i++)//hash:密文->明文            hash[hash[i]]='a'+i;        n=strlen(A);        for(i=0;i<n;i++)            B[i]=hash[A[i]];        B[i]='\0';        getnext();        KMP();    }    return 0;}


 

原创粉丝点击