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

  • 相关阅读:
    494 Target Sum 目标和
    493 Reverse Pairs 翻转对
    492 Construct the Rectangle 构建矩形
    491 Increasing Subsequences 递增子序列
    488 Zuma Game 祖玛游戏
    486 Predict the Winner 预测赢家
    485 Max Consecutive Ones 最大连续1的个数
    483 Smallest Good Base
    Django Form组件
    Django Auth组件
  • 原文地址:https://www.cnblogs.com/vivym/p/3927955.html
Copyright © 2011-2022 走看看