zoukankan      html  css  js  c++  java
  • KMP模板

    感谢 kuangbin大神 http://www.cnblogs.com/kuangbin/archive/2012/08/14/2638803.html

    转一下模板  方便自己查阅

    该算法时间复杂度是O(m+n),  得到Next数组的过程是O(n)

    
    

    /*
    pku3461(Oulipo), hdu1711(Number Sequence)
    这个模板 字符串是从0开始的
    Next数组是从1开始的

    求T串是否为S串的子串?

    主串为 abdabdabc    S串  

          012345678

    模式串 abdabc       T串

          012345

    S[0]=T[0] S[1]=T[1],S[2]=T[2]...S[4]=T[4]

    S[5]!=T[5] 一般情况下重新匹配S[1]和T[0]

    KMP情况下,匹配S[5]和T[2].

    aewasdaw 前缀是包含第一个字符的子串,比如:a,ae,aew,aewa

             后缀是包含最后一个字符的子串,比如w,aw,daw,sdaw.

    Next[k]数组表示前k个字符的前缀和后缀的最大公共长度,也表示下标为k的字符匹配失败后,下一次匹配的下标,等于-1时,代表该字符的匹配已经结束。

    KMP中涉及的前缀和后缀不包括整个字符串,
    */
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;

    
    

    const int N = 1000002;
    int Next[N];
    char S[N], T[N];
    int slen, tlen;//注意每次一定要计算长度

    
    

    void getNext()
    {
        int j, k;
        j = 0; k = -1; Next[0] = -1;
        while(j < tlen)
            if(k == -1 || T[j] == T[k])
                Next[++j] = ++k;
            else
                k = Next[k];

    
    

    }
    /*
    返回模式串T在主串S中首次出现的位置
    返回的位置是从0开始的。
    */
    int KMP_Index()
    {
        int i = 0, j = 0;
        getNext();

    
    

        while(i < slen && j < tlen)
        {
            if(j == -1 || S[i] == T[j])
            {
                i++; j++;
            }
            else
                j = Next[j];
        }
        if(j == tlen)
            return i - tlen;
        else
            return -1;
    }
    /*
    返回模式串在主串S中出现的次数
    */
    int KMP_Count()
    {
        int ans = 0;
        int i, j = 0;

    
    

        if(slen == 1 && tlen == 1)
        {
            if(S[0] == T[0])
                return 1;
            else
                return 0;
        }
        getNext();
        for(i = 0; i < slen; i++)
        {
            while(j>=0 && S[i] != T[j])
                j = Next[j];
            if(j==-1||S[i] == T[j])
                j++;
            if(j == tlen)
            {
                ans++;
                j = Next[j];
            }
        }
        return ans;
    }
    int main()
    {

    
    

        int TT;
        int i, cc;
        scanf("%d",&TT);
        while(TT--)
        {
            scanf("%s",S);
            scanf("%s",T);
            slen = strlen(S);
            tlen = strlen(T);
            cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()<<endl;
            cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl;
        }
        return 0;
    }
    /*
    test case
    aaaaaa a
    abcd d
    aabaa b
    */

    
    
  • 相关阅读:
    pip 安装用 国内清华大学的数据源
    sql server 中导出图片并命名
    金跌 K3 科目表
    SQLSERVER 循环
    语句判断记录是否存在(最简洁简单性能最优)
    增、删、改开放时间表时,同步数据至 CP
    [网络流24题] 圆桌问题(最大流)
    [网络流24题] 最小路径覆盖问题(匈牙利 最大流)
    C. Vasya And Array (贪心构造)
    【牛客网】一个有意思的前缀和题目
  • 原文地址:https://www.cnblogs.com/a249189046/p/7404762.html
Copyright © 2011-2022 走看看