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
  • 相关阅读:
    GB50174-2008《电子信息系统机房设计规范》
    Tickets HDU
    HDU
    [长期更新]题解合集
    网络流/费用流题目总结[持续更新]
    [转载]Maximum Flow: Augmenting Path Algorithms Comparison
    [转载]网络流笔记
    网络流各类算法简单总结与比较
    简单的算法备忘录,个人总结[长期更新]
    训练报告 18春组队04 2014西安全国邀请赛
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3549972.html
Copyright © 2011-2022 走看看