hdu4300 Clairewd’s message(扩展KMP)

题目链接:点击打开链接

题目描述:给定一个字母转换表,然后给一个字符串,字符串的前一部分经字母转换表转换过之后的字符,字符串的后面一部分是未经转换之前的,后面的部分可能不完整,但前面被转换过之后的一定是完整的,求补充不完整的部分(当然也有可能是完整的,如果是完整的直接输出即可),要求尽可能的短?


解题思路:扩展KMP算法(匹配前缀)

分析:相当于让字符串的后面部分尽可能长的匹配前面的部分,所以我们将原串st复制给str1,然后根据转换表,把st全部逆转回来;然后将st当作模板串,str1为带匹配的串,从str1[(len+1)/2]开始匹配即可

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
using namespace std;

void getNext(char* x,int m,int* exnext){
    exnext[0]=m;
    int j=0;
    while(j+1<m&&x[j]==x[j+1]) j++;
    exnext[1]=j;
    int k=1;
    for(int i=2;i<m;++i){
        int p=exnext[k]+k-1;
        int L=exnext[i-k];
        if(i+L<p+1) exnext[i]=L;
        else{
            j=max(0,p-i+1);
            while(i+j<m&&x[i+j]==x[j]) j++;
            exnext[i]=j;
            k=i;
        }
    }
}
void EKMP(char* x,int m,char* y,int n,int* exnext,int* extend){
    getNext(x,m,exnext);
    int j=0;
    while(j<n&&j<m&&x[j]==y[j]) j++;
    extend[0]=j;
    int k=0;
    for(int i=1;i<n;++i){
        int p=extend[k]+k-1;
        int L=exnext[i-k];
        if(i+L<p+1) extend[i]=L;
        else{
            j=max(0,p-i+1);
            while(i+j<n&&j<m&&y[i+j]==x[j]) j++;
            extend[i]=j;
            k=i;
        }
    }
}
char ascii[30];
char st1[MAXN];
char st[MAXN];
int exnext[MAXN];
int extend[MAXN];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s",st1);
        scanf("%s",st);
        for(int i=0;i<26;i++)
            ascii[st1[i]-'a']='a'+i;
        int len=strlen(st);
        memcpy(st1,st,len);
        for(int i=0;i<len;++i)
            st[i]=ascii[st[i]-'a'];
        EKMP(st,len,st1,len,exnext,extend);
        int i;
        for(i=(len+1)/2;i<len;i++) if(extend[i]==len-i)break;
        for(int j=0;j<i;++j) printf("%c",st1[j]);
        for(int j=0;j<i;++j) printf("%c",st[j]);
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值