zoukankan      html  css  js  c++  java
  • 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 则没有循环节???(小声逼逼)
  • 相关阅读:
    yii2 gii 命令行自动生成控制器和模型
    控制器中的方法命名规范
    Vue Property or method "" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based
    IDEA插件:GsonFormat
    Spring Boot : Access denied for user ''@'localhost' (using password: NO)
    Typora添加主题
    Git基础命令图解
    Java Joda-Time 处理时间工具类(JDK1.7以上)
    Java日期工具类(基于JDK1.7版本)
    Oracle SQL Developer 连接Oracle出现【 状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied】
  • 原文地址:https://www.cnblogs.com/duny31030/p/14304217.html
Copyright © 2011-2022 走看看