zoukankan      html  css  js  c++  java
  • hdu 1358 period KMP入门

    Period

    题意:一个长为N (2 <= N <= 1 000 000) 的字符串,问前缀串长度为k(k > 1)是否是一个周期串,即k = A...A;若是则按k从小到大的顺序输出k即周期数;

    Sample Input
    3 aaa
    12 aabaabaabaab
    0
     
    Sample Output
    Test case #1
    2 2
    3 3
     
    Test case #2
    2   2
    6   2
    9   3
    12  4
     题目其实是来自于LA的..挺好的一道题,用的是原版的kmp..
    写写对KMP的理解:
    这里写的kmp直接是从0开始的,并且0,1失配都指向0;kmp的getfail()其实就是用当前确定的p[i] = p[[f[i]]来给i+1一个匹配的机会,(特别注意不是相等)即f[i+1] = j+1;这就是失配边的下标转移;在i+1时,只是找了和p[i]相等的d[f[j]],但是并没有去改变原来的匹配关系,这只是为了递推下去;
    还有需要注意的就是kmp其实匹配到了第len位,这一位原本是''的,但是由于里面的递推下一位的关系,这一位其实也是匹配了的;这道题就能用到第len的匹配关系~~很妙
     
    思路:怎么知道前缀长度为2的串是是周期串?如aa?这时我们需要往后移到1位,我们怎么知道要往后一道以为呢?这正是f[i]的失配边的含义了~~由于若p[0] = p[1] = 'a';那么在p[2]失配时,显然朴素的KMP的f[2] = 1;这就弄成了周期;这也是为什么下面是从2开始到n的;
    还有i代表的就是前缀的长度;即k(i - f[i]) = i,(k > 1)所以f[i] > 0并且(i-f[i])|i;
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e6 + 7;
    char p[N];
    int f[N];
    void getfail(char *p,int *f)
    {
        f[0] = f[1] = 0;
        int n = strlen(p);
        for(int i = 1;i < n;i++){
            int j = f[i];
            if(j && p[i] != p[j]) j = f[j];
            f[i+1] = (p[i] == p[j] ?j+1:0);// i+1会递推到第n位
        }
    }
    int main()
    {
        int n,kase = 1;
        while(scanf("%d",&n) == 1 && n){
            scanf("%s", p);
            getfail(p,f);
            printf("Test case #%d
    ",kase++);
            for(int i = 2;i <= n;i++){// i = n **
                if(f[i] > 0 && i%(i-f[i])==0)
                    printf("%d %d
    ",i,i/(i-f[i]));
            }
            puts("");
        }
    }
     
  • 相关阅读:
    简单的冒泡排序算法(java)
    寻找两个数组中的公共元素Java程序代码
    利用快速排序求两集合交集
    一种简单的吉布斯采样modify中应用
    递归生成小于某个数的所有集合
    卡拉曼算法简答程序
    模态对话框退出DoModal过程中需注意的陷阱
    是否可以使用空对象指针调用成员函数及访问成员变量
    windows c++如何使窗口动态改变位置
    windows的滚动条使用
  • 原文地址:https://www.cnblogs.com/hxer/p/5268201.html
Copyright © 2011-2022 走看看