• KMP算法


    参考《大话数据结构》 P135

    KMP算法用于字符串匹配,kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置。常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(nm)。kmp算法通过一个O(m)的预处理,使匹配的复杂度降为O(n+m)

    思想:

    朴素匹配算法需要两个指针i,j都遍历一遍字符串,故复杂度m*n

    KMP算法i指针不回溯,j指针的回溯参考next数组,体现了动态规划的思想

    原理如下:

    蓝色表示匹配,红色为失配

    分析蓝色部分

    如果存在最长公共前后缀的话,比如这样:

    就可以在下次匹配的时候用,这样避免了i的回溯

    实现:

    next数组的意义:当模式匹配串T失效的时候,next数组对应的元素知道应该使用T串的哪个元素进行下一轮匹配

     1 #include <string>
     2 
     3 void get_next(string T, int *next)
     4 {
     5     int i = 1;    //后缀
     6     int j = 0;    //前缀
     7     next[1] = 0;
     8     while (i < T[0])    //T[0]表示字符串长度
     9     {
    10         if (j == 0 || T[i] == T[j])
    11         {
    12             i++;
    13             j++;
    14             next[i] = j;
    15         }
    16         else
    17             j = next[j];
    18     }
    19 }
    20 
    21 int KMP(string S, string T, int pos)
    22 {
    23     int i = pos;    //标记主串S下标
    24     int j = 1;        //匹配串下标
    25     int next[255];
    26     get_next(T, next);
    27     while (i <= S[0] && j <= T[0])    //0位置都放字符串长度
    28     {
    29         if (j == 0 || S[i] == T[j])
    30         {
    31             i++;
    32             j++;
    33         }
    34         else
    35             j = next[j];    //j退回到合适位置,i不用再回溯了
    36         if (j > T[0])    //如果存在j在匹配完最后一个元素后又++了,所以会大于长度
    37             return i - T[0];    //i的位置减去匹配串的长度就是匹配串出现的位置
    38         else
    39             return 0;
    40     }
    41 }

    改进

    会出现一种特殊情况:

    S = “aaaabcde”

    T = "aaaaax"

    这样的话next数组为012345,实际上由于前面都是a,直接调到第一个a就可以了,期望的next数组为000005

    这样next数组构造改为12-15行

     1 void get_next(string T, int *next)
     2 {
     3     int i = 1;    //后缀
     4     int j = 0;    //前缀
     5     next[1] = 0;
     6     while (i < T[0])    //T[0]表示字符串长度
     7     {
     8         if (j == 0 || T[i] == T[j])
     9         {
    10             i++;
    11             j++;
    12             if (T[i] != T[j])
    13                 next[i] = j;
    14             else
    15                 next[i] = next[j];
    16         }
    17         else
    18             j = next[j];
    19     }
    20 }
  • 相关阅读:
    高精度减法
    HDU 4460 Friend Chains
    POJ 2386 Lake Counting
    POJ 1852 Ants
    HDU 1240 Asteroids!
    SQL注入之Sqli-labs系列第三十六关(基于宽字符逃逸GET注入)和三十七关(基于宽字节逃逸的POST注入)
    SQL注入之Sqli-labs系列第三十四关(基于宽字符逃逸POST注入)和三十五关
    SQL注入之Sqli-labs系列第三十三关(基于宽字符逃逸注入)
    SQL注入之Sqli-labs系列第三十关(基于WAF防护的双引号报错注入)和三十一关
    墨者-uWSGI 漏洞复现(CVE-2018-7490)
  • 原文地址:https://www.cnblogs.com/raichen/p/4988598.html
Copyright © 2020-2023  润新知