zoukankan      html  css  js  c++  java
  • POJ 2541 Binary Witch(逆序KMP,好题)

    逆序KMP,真的是强大!

    参考链接,下面有题意解释:
    http://blog.sina.com.cn/s/blog_6ec5c2d00100tphp.html
    http://blog.csdn.net/sdjzping/article/details/8857749
    http://tech.ddvip.com/2013-09/1380477442203505.html


    直接暴力是枚举字符串的后面13个的字母,然后再用KMP匹配,这样的话,就绪要枚举多次,分别是后面的13,12,11....1个字母。
    但是通过观察可以发现,其实要求的是最长公共后缀! 那么可以把原来的字符串逆序转换一下,就变成了求最长公共前缀!
    这样只需要求一次,用字符串的前面13个字母和原字符串从第二个字符开始进行匹配一次就够了!

    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <string>
    #include <string.h>
    
    using namespace std;
    const int maxn=1000000+1010;
    char s[maxn],str[maxn];
    int next[maxn];
    char ans[1005];  //答案
    int n,l;
    int start=1005; //标记字符串的起始位置
    int k;
    
    void getNext(char*str) {
        next[1]=0;
        int k=0;
        int lm=strlen(str);
        for(int i=1; i<lm; i++) {
            while(k&&str[k]!=str[i])
                k=next[k];
            if(str[i]==str[k])
                k++;
            next[i+1]=k;
        }
    }
    //逆序KMP,转化为求最长公共前缀
    int kmp(char*P,int len) {
        int k=0,c=0,idx;
        int lm=strlen(P);
        for(int i=start+1; i<start+len; i++) {
            while(k&&P[k]!=str[i])
                k=next[k];
            if(P[k]==str[i])
                k++;
            if(k>c){
                c=k;
                idx=i;
            }
            if(k==lm)
                return i-k;
        }
        if(c)
            return idx-c;
        else
            return -1;
    }
    int main()
    {
        char tmp[20];
        scanf("%d%d",&n,&l);
        scanf("%s",&s);
        int len=strlen(s);
        for(int i=0;s[i];i++){
            str[start+i]=s[len-1-i];
        }
        str[start+len]='';
        int cnt=l,k;
        while(cnt--){
            //截取开始的13个字符
            strncpy(tmp,str+start,13);
            if(len<13)
                tmp[len]='';
            else
                tmp[13]='';
            getNext(tmp);
            k=kmp(tmp,len);
            start--;
            len++;
            if(k==-1)
                str[start]='0';  //不存在匹配的情况
            else
                str[start]=str[k];
        }
        for(int i=0;i<l;i++)
            ans[i]=str[start+l-1-i];
        ans[l]='';
        printf("%s
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Eclipse和MyEclipse常出现的错误总结
    JS中的showModelDialog详解和实例
    form中的action,submit="return save()"以及ajax提交方法
    清除上传文件input标签中type="file"的value值
    上传文件时并顺便将文件压缩时出现文件名乱码以及文件内容乱码解决方案
    python 知识
    centos 安装docker
    docker 配置国内镜像
    git 操作命令
    react build dist发布nginx时的配置
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3549972.html
Copyright © 2011-2022 走看看