zoukankan      html  css  js  c++  java
  • KMP算法模板&&扩展

    很不错的学习链接:https://blog.csdn.net/v_july_v/article/details/7041827

    具体思路就看上面的链接就行了,这里只放几个常用的模板

     

    问题描述:

    给出字符串a和b,求a中匹配b的所有下标

     1 const int maxn = 1e6 + 10;
     2 int Next[maxn];
     3 void Getnext(char* p)//next数组初始化
     4 {
     5     int plen = strlen(p);
     6     Next[0] = -1;
     7     int k = -1, j = 0;
     8     while(j < plen - 1)//next优化            j < plen也可以,只是多求了next[plen]
     9     {
    10         //p[k]表示前缀  p[j]表示后缀
    11         if(k == -1 || p[j] == p[k])
    12         {
    13             j++, k++;
    14             if(p[j] != p[k])Next[j] = k;
    15             else Next[j] = Next[k];
    16         }
    17         else k = Next[k];
    18     }
    19     /*while(j < plen - 1)//next数组未优化
    20     {
    21         //p[k]表示前缀  p[j]表示后缀
    22         if(k == -1 || p[j] == p[k])
    23         {
    24             j++, k++;
    25             Next[j] = k;
    26         }
    27         else k = Next[k];
    28     }*/
    29 }
    30 int ans;
    31 void KMP(char* s, char* p)//s为文本串,p为匹配串
    32 {
    33     Getnext(p);ans = 0;//ans为匹配次数
    34     int i = 0, j = 0;
    35     int slen = strlen(s), plen = strlen(p);
    36     while(i < slen)
    37     {
    38         if(j == -1 || s[i] == p[j])
    39             i++, j++;
    40         else j = Next[j];
    41         if(j == plen)//已经匹配
    42         {
    43             ans++;
    44             //cout<<i - j<<endl;//匹配的下标    从0开始
    45             j = next[j];
    46             i--;//如果所匹配的子串之间不可相交,去掉i--;
    47         }
    48     }
    49 }

     KMP另一版本:感觉更快

     1 int Next[maxn];
     2 void Getnext(char p[], int plen)//next数组初始化
     3 {
     4     Next[1] = 0;
     5     int k = 0;
     6     for(int i = 1; i < plen; i++)
     7     {
     8         while(k > 0 && p[k] != p[i])k = Next[k];
     9         if(p[k] == p[i])k++;
    10         Next[i + 1] = k;
    11     }
    12 }
    13 int KMP(char s[], char p[], int slen, int plen)//s为文本串,p为匹配串
    14 {
    15     Getnext(p, plen);//如果匹配串p一直不变,可以在函数外面调用一次即可
    16     int k = 0;
    17     int ans = 0;
    18     for(int i = 0; i < slen; i++)
    19     {
    20         while(k > 0 && p[k] != s[i])k = Next[k];
    21         if(p[k] == s[i])k++;
    22         if(k == plen)
    23         {
    24             ans++;
    25             k = Next[k];//匹配的下标i-j 从0开始
    26         }
    27     }
    28     return ans;
    29 }

    KMP算法扩展:

    https://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html?from=search

     1 //扩展KMP算法
     2 //求字符串S的后缀 与字符串T的最长公共前缀长度
     3 //extand[i]表示S[i...slen] 与 T的最长公共前缀长度
     4 //Next[i]表示T[i...tlen] 与 T的最长公共前缀长度 也就是最长公共前后缀长度
     5 
     6 char s[maxn], t[maxn];
     7 int Next[maxn], extand[maxn];
     8 void Getnext(char t[])//预处理出Next数组
     9 {
    10     int tlen = strlen(t), i = 0;
    11     Next[0] = tlen;//从0开始的后缀(就是T) 和 T的公共前缀就是T本身
    12     while(i < tlen - 1 && t[i] == t[i + 1])i++;
    13     Next[1] = i;
    14     int a = 1;
    15     for(int i = 2; i < tlen; i++)
    16     {
    17         int p = a + Next[a] - 1, L = Next[i - a];//p为当前匹配到的最远位置,a表示从a开始匹配可以匹配到这个最大位置
    18         if(i - 1 + L >= p)//情况2
    19         {
    20             int j = (p - i + 1) > 0 ? (p - i + 1) : 0;
    21             while(i + j < tlen && t[i + j] == t[j])j++;
    22             Next[i] = j;
    23             a = i;
    24         }
    25         else Next[i] = L;//情况1
    26     }
    27 }
    28 void Getextand(char* s, char* t)
    29 {
    30     memset(Next, 0, sizeof(Next));
    31     Getnext(t);
    32     int slen = strlen(s), tlen = strlen(t);
    33     int Minlen = Min(slen, tlen);
    34     int a = 0;
    35     while(a < Minlen && s[a] == t[a])a++;
    36     extand[0] = a;
    37     a = 0;
    38     for(int i = 1; i < slen; i++)
    39     {
    40         int p = a + extand[a] - 1, L = Next[i - a];
    41         if(i - 1 + L >= p)//情况2
    42         {
    43             int j = (p - i + 1) > 0 ? (p - i + 1) : 0;
    44             while(i + j < slen && j < tlen && s[i + j] == t[j])j++;
    45             extand[i] = j;
    46             a = i;
    47         }
    48         else extand[i] = L;
    49     }
    50 }
  • 相关阅读:
    eclipse中文乱码
    学习进度(7)
    校园管家(Android开发团队项目)NABCD
    NABCD(团队项目)
    android studio连接真机大概问题
    01梦断代码阅读笔记
    学习进度(6)
    android studio学习(一)
    地铁出行系统1.0
    学习进度(4)
  • 原文地址:https://www.cnblogs.com/fzl194/p/9333179.html
Copyright © 2011-2022 走看看