• hdu 3746 kmp求字符串循环节


    这道题应该可以早就过的,却拖了一下午=_=,主要是我遇到了很奇怪的问题,现在还不知道原因。

    那就是我一开始写的输入是:

    while(T--&&(scanf("%s",s+1)!=EOF))
    {
         ......
    }

    一直wa,最后实在感觉没错,很无奈,照着别人的代码一个字符一个字符比对,发现改成以下格式就过了:

    while(T--)
    {
          scanf("%s",s+1);
          ......
    }

    我之前也这么写过,应该没问题,猜测了很多原因,包括出题者给的数据不是严格的T组数据等等,但都被我排除了,所以暂时我还是不知道原因是什么,在群里问了也没人回,所以先暂且把它叫做灵异问题吧。

    下面正式进入正题。这道题考察的是kmp next数组的理解,根据next数组求出字符串最小循环节,我用的是比较一般的递推方法。

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int MAXN=100005 ;
    int jump[MAXN];
    void PrintJump(char *str)
    {
        jump[0] = -1;
        jump[1] = 0;
        int len = strlen(str+1);
        int j=1,k;
        while(j<len)            //计算jump[j+1]
        {
            k = jump[j];        //已知jump[j]==k
            while(k!=-1&&str[k+1]!=str[j+1]) k = jump[k];
            jump[j+1] = k+1;
            j++;
        }
    }
    
    char s[MAXN];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",s+1);
            PrintJump(s);
            int len = strlen(s+1);
            int c=1;
            for(int i=2;i<=len;i++) {
                int t=jump[i];
                int tc=i%c;
                if(tc==0) tc+=c;
                while(t>tc) t=jump[t];
                if(t<tc) {
                    c=i-jump[i];
                }
                //printf("%d %d
    ",c,t);
            }
            //printf("count = %d
    ",c);
            int ans=len%c;
            if(c==len) ans = len;
            else if(ans) ans = c-ans;
            printf("%d
    ",ans);
        }
    }

    但有人已经证明出来len-next[i]就是字符串的最小循环节,这样复杂度就大大降低了:http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html。值得学习。

  • 相关阅读:
    大数据学习笔记01
    寻址方式
    指令格式
    虚拟存储器
    高速缓冲存储器Cache
    双端口RAM和多模块存储器
    主存储器与CPU的连接
    半导体存储器
    存储系统——基本概念
    算术逻辑单元
  • 原文地址:https://www.cnblogs.com/lastone/p/5312887.html
Copyright © 2020-2023  润新知