zoukankan      html  css  js  c++  java
  • KMP算法类习题——字符串匹配

    Description

    For each prefix with length P of a given string S,if

    S[i]=S[i+P] for i in [0..SIZE(S)-p-1],

    then the prefix is a “period” of S. We want to all the periodic prefixs.

    Input

    Input contains multiple cases.

    The first line contains an integer T representing the number of cases. Then following T cases.

    Each test case contains a string S (1 <= SIZE(S) <= 1000000),represents the title.S consists of lowercase ,uppercase letter.

    Output

    For each test case, first output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the number of periodic prefixs.Then output the lengths of the periodic prefixs in ascending order.

    Sample Input

    4
    ooo
    acmacmacmacmacma
    fzufzufzuf
    stostootssto
    

    Sample Output

    Case #1: 3
    1 2 3
    Case #2: 6
    3 6 9 12 15 16
    Case #3: 4
    3 6 9 10
    Case #4: 2
    9 12


    参考代码:

    #include <cstdio>

    #include <cstring>

    const int maxn = 1000010;

    int p[maxn],ans[maxn];

    char str[maxn]; //保存字符串的数组

     

    void get_p(int len){

        p[1] = 0;

        int j = 0;

        for(int i = 2;i <= len;i++){

            while(j > 0 && str[j+1] != str[i])  j = p[j];

    //这个循环是当结果失配时才使用的

            if(str[j+1] == str[i])  j++;

            p[i] = j;

        }

    }

     

    int main(){

        int nkase;

        scanf("%d",&nkase);

        for(int kase = 1;kase <= nkase;kase++){

            scanf("%s",str+1);

    // 这个+1表示的含义是从下标为1的地方开始输入,方便后续的操作

    //C中这样控制字符串输入的格式还是非常方便的 

            int len = strlen(str+1);

            get_p(len);  

    //这个是单单初始化了数组p得到了结果,然后主要的思想未知,可能是在求解next数组

    //str的长度告诉函数,通过匹配的方式得到数组p,相当于next数组

            int t = p[len],cnt = 0;

            while(t){

                ans[cnt++] = len-t;

                t = p[t];

    //每次取到的数值是一定会比以前的要小,所以这不可能是一个死循环的

            }

            ans[cnt++] = len;

    //在这里将所有的运算结果全部保留下来,包括数量cnt和最后输出的结果ans[];

            printf("Case #%d: %d ",kase,cnt);

    //在这里有两个参数,即运行的次数和返回的结果数

            for(int i = 0;i < cnt-1;i++)  printf("%d ",ans[i]);

           printf("%d ",ans[cnt-1]);

     

        }

        return 0;

    }

    关键点分析:

    本题还是要先找到next数组,然后通过next数组来访问求解。

    当然,每个next数组保存的内容都是不一样的,都是前一个字符匹配得到的信息结果保留在那个地方。

    //KMP的算法重点就是求解next数组,当求解next数组时要知道关键点就是next数组中保存的数据是什么意思,那是当失配的时候后缀部分和前面的部分是否相同的表现

    我要坚持一年,一年后的成功才是我想要的。
  • 相关阅读:
    有序矩阵中的第 k 个最小数组和
    查找和最小的K对数字
    前 K 个高频元素
    621. 任务调度器
    407. 接雨水 II
    c语言表达式求值 中缀表达式转后缀表达式 求值
    42. 接雨水
    MySQL高级特性——绑定变量
    MySQL高级特性之分区表
    MySQL优化特定类型的查询
  • 原文地址:https://www.cnblogs.com/tianxia2s/p/3872928.html
Copyright © 2011-2022 走看看