zoukankan      html  css  js  c++  java
  • KMP 和 扩展KMP

    KMP:在主串S中找子串T的位置KMP算法的时间复杂度O(|S|+|T|)。

    #define maxn 1000
    char s[maxn],t[maxn];//s为主串,t为子串
    int net[maxn],l1,l2;//l1为主串长度,l2为子串长度
    void get_next() {
        int i=0,j=-1;
        net[0]=-1;
        while(i<l2) {
            if (j==-1 ||t[i]==t[j])
            {
                ++i,++j;
                if (t[i]!=t[j]) net[i]=j; //优化next数组
                else net[i]=net[j];
            }
            else j=net[j];
        }
        /*for (i=0;i<l2;i++)
            printf("next[%d]=%d
    ",i,next[i]);  */
    }
    //返回子串在主串第pos个字符之后的位置
    //若不存在则返回0
    int KMP(int pos)
    {
        int i=pos,j=0;
        get_next();       //核心部分
        while(i<l1&&j<l2) {
            if (j==-1||s[i]==t[j]) i++,j++;
            else j=net[j];
        }
        if (j==l2) return i-l2;
        else return 0;
    }
    1
    void getNext() {
        Next[1] = 0;
        for (int i = 2, j = 0; i <= n; i++) {
            while(j > 0 && a[i] != a[j+1]) j = Next[j];
            if (a[i] == a[j+1]) j++;
            Next[i] = j;
        } 
    }
    void KMP() {
        for (int i = 1, j = 0; i <= m; i++) {
            while(j > 0 && (j == n || b[i] != a[j+1])) 
                j = Next[j]; 
            if (b[i] == a[j+1]) j++;
            f[i] = j;
            // if (f[i] == n) 此时是A在B中的某一次出现
        }
    }
    2(来着算法竞赛进阶指南)

    扩展KMP: 

    给定串S,和串T,设S的长度为n,T的长度为m,求T与S的每一个后缀(包括S)的最长公共前缀。复杂度为O(n+m)。

    设extend数组,extend[i]表示T与S[i,n-1]的最长公共前缀,要求出所有extend[i](0<=i<n)。

    注意到,如果有一个位置extend[i]=m,则表示T在S中出现,而且是在位置i出现,这就是标准的KMP问题,所以说拓展kmp是对KMP算法的扩展,所以一般将它称为扩展KMP算法。

    详细过程参考博客: https://blog.csdn.net/qq_40160605/article/details/80407554

              https://blog.csdn.net/dyx404514/article/details/41831947

    const int K=1000005;
    int nt[K],extand[K];
    char S[K];
    void Getnext(char *T,int *next)
    {
        int len=strlen(T),a=0;
        next[0]=len;
        while(a<len-1 && T[a]==T[a+1]) a++;
        next[1]=a;
        a=1;
        for(int k=2; k<len; k++)
        {
            int p=a+next[a]-1,L=next[k-a];
            if( (k-1)+L >= p)
            {
                int j = (p-k+1)>0 ? (p-k+1) : 0;
                while(k+j<len && T[k+j]==T[j]) j++;
                next[k]=j;
                a=k;
            }
            else next[k]=L;
        }
    }
    void GetExtand(char *S,char *T,int *next)
    {
        Getnext(T,next);
        int slen=strlen(S),tlen=strlen(T),a=0;
        int MinLen = slen < tlen ? slen : tlen;
        while(a<MinLen && S[a]==T[a]) a++;
        extand[0]=a;
        a=0;
        for(int k=1; k<slen; k++)
        {
            int p=a+extand[a]-1, L=next[k-a];
            if( (k-1)+L >= p)
            {
                int j= (p-k+1) > 0 ? (p-k+1) : 0;
                while(k+j<slen && j<tlen && S[k+j]==T[j]) j++;
                extand[k]=j;
                a=k;
            }
            else extand[k]=L;
        }
    }
    int main()
    {
        while(scanf("%s%s",S,T)==2)
        {
            GetExtand(S,T,nt); 
            for(int i=0; i<strlen(T); i++)
                printf("%d ",nt[i]);
            puts("");
            for(int i=0; i<strlen(S); i++)
                printf("%d ",extand[i]);
            puts("");
        }
        return 0;
    }
    扩展KMP
  • 相关阅读:
    代理工具介绍
    Cookie 相关
    在JavaScript 使用命名空间
    oracle rank()用法
    sql update 特殊用法
    Repeat 嵌套绑定
    .net 中隐式事务和显示事务的用法
    为站点添加迅雷下载和快车下载
    缺少MSVCR71.DLL解决方式
    关于AppFabric Caching的学习摘录
  • 原文地址:https://www.cnblogs.com/l999q/p/11304900.html
Copyright © 2011-2022 走看看