zoukankan      html  css  js  c++  java
  • EX_KMP算法总结

    EX_KMP算法总结

    By viv

    2014-8-9 0:30

    吐槽1:字符串神马的我最讨厌了,但不学不行啊。TAT

    吐槽2:写这东西差点错过CF(codeforces).

    今天学了ex_kmp,故总结一下。(记性不好,学了的东西,说不定过两天就忘了)

    先说说ex_kmp算法求得什么:

    给定字符串T,P, n = |T| , m = |P|,定义ex[i] = T[i …n]和P的最长公共前缀的长度。

    这就是ex_kmp问题,ex_kmp算法就死在线性时间内求得所有的ex[i]。

    我们可以发现,如果ex[i] = m,则P在T中出现过,且位置为i,这正是KMP所求得东西。由此可见ex_kmp算法是对kmp的扩展。

    下面说一下ex_kmp算法的流程(下表从0开始,当前节点为k,设P自己进行ex_kmp得到的ex数组为f数组):

    假设ex[0,k)已经求好,在匹配中,到达的最远距离为p,即p为i + ex[i]的最大值,我们设取最大值的i为a。

    这样我们可以得到以下几个关系:

    T[a,p] = P[0,p - a]

    T[k,p] = P[k – a,p - a]

    这样,我们可以分两种情况:(用mspaint画的,很丑,字母大小写问题也不要在意了,明白就行)

    情况1:

    clip_image002

    如上图,如果 K + f[k - a] < p的话,显然,图中灰色部分一定相同,蓝色部分一定不同。这样一来,f[k] = f[k - a] 且 a , p 的值不变。

    情况2:

    clip_image004

    如上图,如果K+f[k - a] >= p的话,则,图中蓝色部分相同,紫色部分未知。这种情况下,我们就可以直接从p+1位开始匹配,直到失配。然后更新a , p的值。

    就这样,整个算法已经完结了。至于f数组,自己和自己匹配一下就可以啦。

    ex_kmp模板:

    void getFail(char *T)
    {
        int idx = 0, mx = 0,n = strlen(T);
        f[0] = n;
        for (int i = 1; i < n; i++)
        {
            if (mx > i + f[i - idx])
            {
                f[i] = f[i - idx];
                continue;
            }
            f[i] = max(mx - i, 0);
            while (T[i + f[i]] == T[f[i]])
                f[i]++;
            if (i + f[i] > mx)
                mx = i + f[i], idx = i;
        }
    }
    
    void ex_kmp(char *T, char *P)
    {
        getFail(P);
        int idx = 0, mx = 0,n = strlen(T);
        for (int i = 0; i < n; i ++)
        {
            if (mx > i + f[i - idx])
            {
                ex[i] = ex[i - idx];
                continue;
            }
            ex[i] = max(mx - i, 0);
            while ((i + ex[i] < n) && T[i + ex[i]] == P[ex[i]])
                ex[i]++;
            if (i + ex[i] > mx)
                mx = i + ex[i], idx = i;
        }
    }

    END

  • 相关阅读:
    Druid Monitor开启登录界面
    nginx强制使用https访问(http跳转到https)
    技术与架构
    SQLProfiler_SQL抓包
    SQL UPDATE with INNER JOIN
    MYSQL业务数据简单脱敏方案
    阿里云CodePipeline vs Jenkins
    Java Profiling & Profilers
    LINUX操作系统(centos6.9)安装与配置
    分布式ID生成系统 UUID与雪花(snowflake)算法
  • 原文地址:https://www.cnblogs.com/vivym/p/3927955.html
Copyright © 2011-2022 走看看