zoukankan      html  css  js  c++  java
  • [KMP]

    KMP未优化:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    /* P 为模式串,下标从 0 开始 */
    void GetNext(string P, int next[])
    {
        int p_len = P.size();
        int i = 0;   // P 的下标
        int j = -1;  
        next[0] = -1;
    
        while (i < p_len - 1)
        {
            if (j == -1 || P[i] == P[j])
            {
                i++;
                j++;
                next[i] = j;
            }
            else
                j = next[j];
        }
    }
    
    /* 在 S 中找到 P 第一次出现的位置 */
    int KMP(string S, string P, int next[])
    {
        GetNext(P, next);
    
        int i = 0;  // S 的下标
        int j = 0;  // P 的下标
        int s_len = S.size();
        int p_len = P.size();
    
        while (i < s_len && j < p_len)
        {
            if (j == -1 || S[i] == P[j])  // P 的第一个字符不匹配或 S[i] == P[j]
            {
                i++;
                j++;
            }
            else
                j = next[j];  // 当前字符匹配失败,进行跳转
        }
    
        if (j == p_len)  // 匹配成功
            return i - j;
        
        return -1;
    }
    View Code

    KMP优化:

     1 void GetNextval(string P, int nextval[])
     2 {
     3     int p_len = P.size();
     4     int i = 0;   // P 的下标
     5     int j = -1;  
     6     nextval[0] = -1;
     7 
     8     while (i < p_len - 1)
     9     {
    10         if (j == -1 || P[i] == P[j])
    11         {
    12             i++;
    13             j++;
    14           
    15             if (P[i] != P[j])
    16                 nextval[i] = j;
    17             else
    18                 nextval[i] = nextval[j];  // 既然相同就继续往前找真前缀
    19         }
    20         else
    21             j = nextval[j];
    22     }
    23 }
    View Code

    KMP算法(未优化版): next数组表示最长的相同真前后缀的长度,我们不仅可以利用next来解决模式串的匹配问题,也可以用来解决类似字符串重复问题等等,这类问题大家可以在各大OJ找到,这里不作过多表述。

    KMP算法(优化版): 根据代码很容易知道(名称也改为了nextval),优化后的next仅仅表示相同真前后缀的长度,但不一定是最长(称其为“最优相同真前后缀”更为恰当)。此时我们利用优化后的next可以在模式串匹配问题中以更快的速度得到我们的答案(相较于未优化版),但是上述所说的字符串重复问题,优化版本则束手无策。

    EXKMP:

     1 void Get_Next(char *S, int *next) {
     2     int lenS = strlen(S + 1), p = 1, pos;
     3     next[1] = lenS; // 对于 next[1] 要特殊考虑
     4     while (p + 1 <= lenS && S[p] == S[p + 1]) ++ p;
     5     next[pos = 2] = p - 1; // next[2] 是为了初始化
     6  
     7     For (i, 3, lenS) { // 注意此时 k + 1 = i
     8         int len = next[i - pos + 1];
     9         if (len + i < p + 1) next[i] = len; // 对应上面第一种情况
    10         else {
    11             int j = max(p - i + 1, 0); // 找到前面对于 子串 最靠后已经匹配的位置
    12             while (i + j <= lenS && S[j + 1] == S[i + j]) ++ j; // 第二种需要暴力匹配
    13             p = i + (next[pos = i] = j) - 1; // 记得更新 p, pos
    14         }
    15     }
    16 }
    17  
    18 void ExKMP(char *S, char *T, int *next, int *extend) {
    19     int lenS = strlen(S + 1), lenT = strlen(T + 1), p = 1, pos;
    20  
    21     while (p <= lenT && S[p] == T[p]) ++ p;
    22     p = extend[pos = 1] = p - 1; // 初始化 extend[1]
    23  
    24     For (i, 2, lenS) {
    25         int len = next[i - pos + 1];
    26         if (len + i < p + 1) extend[i] = len;
    27         else {
    28             int j = max(p - i + 1, 0);
    29             while (i + j <= lenS && j <= lenT && T[j + 1] == S[i + j]) ++ j;
    30             p = i + (extend[pos = i] = j) - 1;
    31         }
    32     } // 和上面基本一模一样啦
    33 }
    View Code
  • 相关阅读:
    poj 1286 Necklace of Beads poj 2409 Let it Bead HDU 3923 Invoker <组合数学>
    大圣降妖录破解
    dex文件格式二
    dex文件格式一
    打造smali代码库辅助分析
    一键调试脚本使用手册
    TraceView进行性能分析
    Android Killer工具用法
    十三. JEB破解三
    十二. 一步步破解JEB 2.0demo版二
  • 原文地址:https://www.cnblogs.com/Kaike/p/11686290.html
Copyright © 2011-2022 走看看