• KMP算法模板


    概述

    模板出自kuangbin的博客

    典型应用:

    给你两个字符串,寻找其中一个字符串是否包含另一个字符串,如果包含,返回包含的起始位置。 

    (1) 头文件

    1 #include <bits/stdc++.h>
    2 using namespace std;
    3 const int N = 1e5+10;
    4 int Next[N];
    5 char S[N],T[N];   // S:主串  T:模式串
    6 int slen,tlen;

    (2) getNext()函数

     1 void getNext()
     2 {
     3     int j,k;
     4     j = 0;  k = -1; Next[0] = -1;
     5     while(j < tlen)
     6     {
     7         if(k == -1 || T[j] == T[k])
     8             Next[++j] = ++k;
     9         else 
    10             k = Next[k];
    11     }
    12 }

    (3) 返回模式串T在主串S中首次出现的位置

     1 // 返回模式串T在主串S中首次出现的位置
     2 // 返回的位置是从0开始的
     3 int KMP_Index()
     4 {
     5     int i = 0,j = 0;
     6     getNext();
     7 
     8     while(i < slen && j < tlen)
     9     {
    10         if(j == -1 || S[i] == T[j])
    11         {
    12             i++;    j++;
    13         }
    14         else 
    15             j = Next[j];
    16     }
    17     if(j == tlen)
    18         return i-tlen;
    19     else 
    20         return -1;
    21 }

    (4) 返回模式串在主串S中出现的次数

     1 int KMP_Count()
     2 {
     3     int ans = 0;
     4     int i,j = 0;
     5 
     6     if(slen == 1 && tlen == 1)
     7     {
     8         if(S[0] == T[0])
     9             return 1;
    10         else 
    11             return 0;
    12     }
    13     getNext();
    14     for(i = 0;i < slen;i++)
    15     {
    16         while(j > 0 && S[i] != T[j])
    17             j = Next[j];
    18         if(S[i] == T[j])
    19             j++;
    20         if(j == tlen)
    21         {
    22             ans++;
    23             j = Next[j];
    24         }
    25     }
    26     return ans;
    27 }

    (5) 全家福

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 /***************KMP***************/
     5 const int N = 1e5+10;
     6 int Next[N];
     7 char S[N],T[N];   // S:主串  T:模式串
     8 int slen,tlen;
     9 
    10 void getNext()
    11 {
    12     int j,k;
    13     j = 0;  k = -1; Next[0] = -1;
    14     while(j < tlen)
    15     {
    16         if(k == -1 || T[j] == T[k])
    17             Next[++j] = ++k;
    18         else 
    19             k = Next[k];
    20     }
    21 }
    22 
    23 // 返回模式串T在主串S中首次出现的位置
    24 // 返回的位置是从0开始的
    25 int KMP_Index()
    26 {
    27     int i = 0,j = 0;
    28     getNext();
    29 
    30     while(i < slen && j < tlen)
    31     {
    32         if(j == -1 && S[i] == T[j])
    33         {
    34             i++;    j++;
    35         }
    36         else 
    37             j = Next[j];
    38     }
    39     if(j == tlen)
    40         return i-tlen;
    41     else 
    42         return -1;
    43 }
    44 
    45 // 返回模式串在主串S中出现的次数
    46 int KMP_Count()
    47 {
    48     int ans = 0;
    49     int i,j = 0;
    50 
    51     if(slen == 1 && tlen == 1)
    52     {
    53         if(S[0] == T[0])
    54             return 1;
    55         else 
    56             return 0;
    57     }
    58     getNext();
    59     for(i = 0;i < slen;i++)
    60     {
    61         while(j > 0 && S[i] != T[j])
    62             j = Next[j];
    63         if(S[i] == T[j])
    64             j++;
    65         if(j == tlen)
    66         {
    67             ans++;
    68             j = Next[j];
    69         }
    70     }
    71     return ans;
    72 }
    73 /***************END***************/
    74 
    75 int main()
    76 {
    77     int TT;
    78     cin >> TT;
    79     while(TT--)
    80     {
    81         cin >> S >> T;
    82         slen = strlen(S);
    83         tlen = strlen(T);
    84         cout << "模式串T在主串中首次出现的位置是: " << KMP_Index() << endl;
    85         cout << "模式串T在主串S中出现的次数为: " << KMP_Count() << endl;
    86     }
    87     return 0;
    88 }
    View Code

    (6) 补充

    KMP的优化

     1 void getNext()
     2 {
     3     int j,k;
     4     j = 0,k = -1,Next[0] = -1;
     5     while(j < tlen)
     6     {
     7         if(k == -1 || T[j] == T[k])
     8         {
     9             j++,k++;
    10             if(T[j] == T[k])
    11                 Next[j] = Next[k];   // 直接走到下一个不相等的地方
    12             else 
    13                 Next[j] = k;
    14         }
    15         else 
    16             k = Next[k];
    17     }
    18 }

    Next[]数组求循环节
    性质:

    • len-next[i]为此字符串的最小循环节(i为字符串的结尾) 
    • 另外如果len%(len-next[i])==0,此字符串的最小周期就为len/(len-next[i])
    • 如果len%(len-next[i]) != 0 则没有循环节???(小声逼逼)
  • 相关阅读:
    【4N魔方阵】
    【2(2N+1)魔方阵 】
    【二分查找法(折半查找法)】
    【循环搜寻法(使用卫兵)】
    【合并排序法】
    【快速排序法一】
    【快速排序二】
    【快速排序三】
    【数据结构】之 线性表详解
    【计算机网络基础】
  • 原文地址:https://www.cnblogs.com/duny31030/p/14304217.html
Copyright © 2020-2023  润新知