hdu 4300 Clairewd’s message KMP算法

题意:

先给定密文到明文的转换表,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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值