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 */