题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1686
题目描述:
给出两个串,分别为a,b,问a串在b串中出现了几次?(其实位置不同,就算不同的串)
解题思路:
字符串匹配首选KMP算法,刚开始的时候,每次匹配成功一个子串后,我就把母串中的指针指向匹配成功的子串起始位置加一处。无疑TLE,ORZ.jpg。
最后想到如果子串很长的话并且出现的字符很单一,算法的复杂度就降为O(M*N)了,GG。其实把匹配到子串末位后,把当前的情况当做失配就好了,移动子串中的指针到对应的Next值处。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 8 #define LL long long 9 #define maxn 10010 10 #define mod 100000007 11 12 char a[maxn*100], b[maxn]; 13 int Next[maxn], n, m; 14 15 void Get_Next (char b[], int m) 16 { 17 int i, j; 18 j = Next[0] = -1; 19 i = 0; 20 21 while (i < m) 22 { 23 while (j!=-1 && b[i]!=b[j]) 24 j = Next[j]; 25 26 Next[++ i] = ++ j; 27 } 28 } 29 30 int kmp (char a[], char b[]) 31 { 32 int ans, i, j; 33 i = j = ans = 0; 34 35 Get_Next (b, m); 36 37 while (i < n) 38 { 39 while (j!=-1 &&a[i] != b[j]) 40 j = Next[j]; 41 42 j++, i++; 43 44 if (j == m) 45 { 46 ans ++; 47 j = Next[j];///匹配成功后,当做失配,移动j到Next处 48 } 49 } 50 return ans; 51 } 52 53 int main () 54 { 55 int T; 56 scanf ("%d", &T); 57 58 while (T --) 59 { 60 scanf ("%s %s", b, a); 61 62 n = strlen (a); 63 m = strlen (b); 64 65 printf("%d ", kmp(a, b)); 66 } 67 return 0; 68 } 69