hdu 4300 Clairewd’s message KMP算法

来源:互联网 发布:数据etl具体工作内容 编辑:程序博客网 时间:2024/06/04 17:57

题意:

先给定密文到明文的转换表,26个字母,第i个字母c[i]表示密文中的c[i]会转换成明文中的'a'+i。

之后给定一串字符串a,表示密文+明文的组合文本,明文部分由密文部分转换过来,现在不清楚是否完整,让我们求最小长度的可能文本。

题解:

题目的要求就是用最短的字符串补完a,使得a的前半部分翻译后可以得到后面部分。

我们先将a全当做密文转换成b,然后从a的后半部分开始匹配(密文肯定不小明文的长度),得到最大的a的后缀等于b的前缀,说明这部分是明文部分,然后补全即可。




代码:

#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <iostream>#include <algorithm>#include <queue>#include <map>#include <vector>using namespace std;const int maxn=1e5+10;char a[maxn],b[maxn],c[30],d[30];int f[maxn];void getFail(char *P,int *f)//求失配函数{    int m=strlen(P);    f[0]=f[1]=0;    for(int i=1;i<m;i++)    {        int j=f[i];        while(j&&P[i]!=P[j])j=f[j];        f[i+1]=P[i]==P[j]?j+1:0;    }}int find(char *T,char *P,int *f)//KMP算法{    int n=strlen(T),m=strlen(P);    getFail(P,f);    int j=0;    for(int i=0;i<n;i++)    {        while(j&&P[j]!=T[i])j=f[j];        if(P[j]==T[i])j++;        //if(j==m)printf("%d\n",i-m+1);    }    return j;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%s%s",c,a);        int i,j,k,n;        for(i=0;i<26;i++)        {            d[c[i]-'a']='a'+i;        }        n=strlen(a);        for(i=0;i<n;i++)b[i]=d[a[i]-'a'];        k=find(a+(n+1)/2,b,f);        //printf("%d\n",k);        for(i=0;i<n-k;i++)printf("%c",a[i]);        for(i=0;i<n-k;i++)printf("%c",b[i]);        printf("\n");    }    return 0;}


0 0
原创粉丝点击