kmp算法(模板)

看毛片算法的核心在于next数组移动,B站的看毛片视频讲解的还是很清楚的

主要是利用了前缀和后缀的匹配,通过对模板串的预处理还完成,时间复杂度是O(m+n)

而朴素算法的时间复杂度为O(nm),但是如果数据是随机的

朴素算法和kmp算法的差距其实不是很大(显示情况下)。

貌似通用的是BM算法来进行匹配的

下面的是看毛片模板:

 

//原理同B站kmp算法讲解

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 using namespace std;
  5 #define maxe 1000002
  6 
  7 int next[maxe];
  8 char S[maxe], T[maxe];
  9 int slen, tlen;
 10 
 11 void getNext()
 12 {
 13     int j, k;
 14     j = 0;
 15     k = -1;
 16     next[0] = -1;
 17     while(j < tlen)
 18         if(k == -1 || T[j] == T[k])
 19 //这个地方先执行 ++k,然后执行++j 最后赋值
 20             next[++j] = ++k;
 21 //表示T[j-1]和T[k-1]相匹配,当j处失配时,直接用next[j]处来匹配当前失配处
 22         else
 23             k = next[k];
 24 }
 25 
 26 /*
 27 返回模式串T在主串S中首次出现的位置
 28 返回的位置是从0开始的。
 29 */
 30 int KMP_Index()
 31 {
 32     int i = 0, j = 0;
 33     getNext();
 34     while(i < slen && j < tlen){
 35         if(j == -1 || S[i] == T[j]){
 36             i++;
 37             j++;
 38         }
 39         else
 40             j = next[j];
 41     }
 42     if(j == tlen)
 43         return i - tlen;
 44     else
 45         return -1;
 46 }
 47 
 48 /*
 49 返回模式串在主串S中出现的次数
 50 */
 51 int KMP_Count()
 52 {
 53     int ans = 0;
 54     int i, j = 0;
 55     if(slen == 1 && tlen == 1){
 56         if(S[0] == T[0])
 57             return 1;
 58         else
 59             return 0;
 60     }
 61 
 62     getNext();
 63     for(i = 0; i < slen; i++){
 64         while(j > 0 && S[i] != T[j])
 65             j = next[j];
 66         if(S[i] == T[j])
 67             j++;
 68         if(j == tlen){
 69             ans++;
 70             j = next[j];
 71         }
 72     }
 73     return ans;
 74 
 75 }
 76 
 77 int main()
 78 {
 79     int TT;
 80     int i, cc;
 81     scanf("%d",&TT);
 82     while(TT--)
 83     {
 84         scanf("%s %s",&S,&T);
 85         slen = strlen(S);
 86         tlen = strlen(T);
 87         getNext();
 88         for(int i=1; i<=tlen; i++)
 89             printf("%d ",next[i]);
 90         printf("\n");
 91         cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()<<endl;
 92         cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl;
 93     }
 94     return 0;
 95 }
 96 
 97 /*
 98 3
 99 ababcabcacbabcac
100 abcac
101 */

 

posted @ 2017-05-02 20:41  啦啦啦天啦噜  阅读(192)  评论(0编辑  收藏  举报