KMP算法
第一次用繁體字寫裝一下逼...
KMP算法是一種改進的字符串匹配算法。KMP算法的關鍵是利用匹配失敗後的信息,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。
具體的實現就是實現一個next函數,函數本身包含了模式串的局部匹配的信息。當然我還不是很懂的...
第一步是得到next數組,next[i]代表的是當前位置i字符跳的步長,就是跳回去下一步應該進行的匹配的位置;
第二步根據next數組找到匹配的位置,一般找到第一個就好了,當然也可以找出一共有多少個匹配的,貌似功能挺多的...
來几題:
通過KMP算法找出模式串在主串中出現的個數:
1 // poj 3461.Oulipo 2 // KMP算法 统计子串匹配次数 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 9 using namespace std; 10 11 int n; //目标串长度 12 int m; //源串长度 13 char t[10005]; //目标串 14 char s[1000005]; //源串 15 int next[10005]; //next数组 16 17 void get_next() 18 { 19 int i = 0, j = -1; 20 next[0] = -1; 21 while(i < n) 22 { 23 if(j == -1 || t[i] == t[j]) //对目标串处理得到next数组 24 { 25 i++, j++; 26 next[i] = j; 27 } 28 else 29 j = next[j]; 30 } 31 } 32 33 int KMP() 34 { 35 int count = 0; 36 get_next(); 37 int i=0, j=0; 38 while(i != m) 39 { 40 if(j == -1 || s[i] == t[j]) 41 i++, j++; 42 else 43 j = next[j]; 44 if(j == n) 45 { 46 count++; //每次找到匹配的子串,count++; 47 j = next[j]; 48 } 49 } 50 if(count == 0) 51 return 0; //匹配失败 52 return count; 53 } 54 55 int main() 56 { 57 int k; 58 scanf("%d", &k); 59 while(k--) 60 { 61 memset(next, 0, sizeof(next)); 62 scanf("%s", t); 63 scanf("%s", s); 64 n = strlen(t); 65 m = strlen(s); 66 int ans = KMP(); 67 printf("%d\n", ans); 68 } 69 return 0; 70 }
接下來這題可以更好的加深對next數組的理解:
很奇怪要用G++編譯才能過...
// poj 2406.Power Strings // KMP算法 找出組成主串的重複子串 // e.g. abababa -> ab // references: // http://blog.sina.com.cn/s/blog_6635898a0100l3sd.html #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1000005; char s[N]; int next[N]; int len; int get_next() { int i = 0, j = -1; next[0] = -1; while(i < len) { if(j == -1 || s[i] == s[j]) { i++, j++; next[i] = j; } else j = next[j]; } } int main() { while(scanf("%s", s) != EOF) { if(s[0] == '.') break; len = strlen(s); get_next(); int ans = 1; if(len % (len - next[len]) == 0) ans = len / (len - next[len]); printf("%d\n", ans); } return 0; }
跟上一題一樣的,只是輸出不同;這題輸出第幾個位置出現來多少次子串,舉個栗子:
aabaabaabaab...
輸出
3 1 表示到第三個位置出現一個aab,就是這麼簡單!!!
1 // poj 1961.Period 2 // KMP算法 poj 2406的加強版而已 3 // references: 4 // http://blog.csdn.net/niushuai666/article/details/6967716 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 #include <algorithm> 9 10 using namespace std; 11 12 const int N = 1000005; 13 14 char s[N]; 15 int next[N]; 16 int len; 17 18 int get_next() 19 { 20 memset(next, 0, sizeof(next)); 21 int i = 0, j = -1; 22 next[0] = -1; 23 while(i < len) 24 { 25 if(j == -1 || s[i] == s[j]) 26 { 27 i++, j++; 28 next[i] = j; 29 } 30 else 31 j = next[j]; 32 } 33 } 34 35 int main() 36 { 37 int k=1; 38 while(scanf("%d", &len) != EOF, len) 39 { 40 scanf("%s", s); 41 get_next(); 42 int ans = 1; 43 int count = 0; 44 printf("Test case #%d\n", k++); 45 for(int i=1; i<=len; i++) 46 { 47 if(i % (i - next[i]) == 0) 48 { 49 ans = i / (i - next[i]); 50 if(ans != 1) 51 printf("%d %d\n", i, ans); 52 53 } 54 } 55 printf("\n"); 56 } 57 return 0; 58 }
一次過三題,你值得擁有!!!