题目描述:
ZJM 的女朋友是一个书法家,喜欢写一些好看的英文书法。有一天 ZJM 拿到了她写的纸条,纸条上的字暗示了 ZJM 的女朋友 想给 ZJM 送生日礼物。ZJM 想知道自己收到的礼物是不是就是她送的,于是想看看自己收到的礼物在纸条中出现了多少次。
Input
第一行输入一个整数代表数据的组数
每组数据第一行一个字符串 P 代表 ZJM 想要的礼物, 包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 并且字符串长度满足 1 ≤ |P| ≤ 10,000 (|P| 代表字符串 P 的长度).
接下来一行一个字符串 S 代表 ZJM 女朋友的纸条, 也包含英语字符 {‘A’, ‘B’, ‘C’, …, ‘Z’}, 满足 |P| ≤ |S| ≤ 1,000,000.
Output
输出一行一个整数代表 P 在 S中出现的次数.
Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
1
2
3
4
5
6
7
Sample Output
1
3
0
1
2
3
思路:
KMP算法直接用
KMP的精髓在于子模式串的匹配,即next数组的计算。
利用next数组可以避开明显不可能匹配的情况,降低时间复杂度。
时间复杂度:O(mn)---->O(n) //m为模式串
1 #include<iostream> 2 #include<istream> 3 #include<string> 4 #include<cstring> 5 #include<cstdio> 6 using namespace std; 7 8 char *str1 = new char[1000010]; 9 char *str2 = new char[1000010]; 10 int j; 11 int *Next = new int[1000010]; 12 void getNext(char ptr[],int len){ 13 //Next = new int[len]; 14 Next[0]=0; 15 for(int i=1,j=0;i<len;i++){ 16 while(j && ptr[i]!=ptr[j]) j=Next[j-1]; 17 if(ptr[i]==ptr[j]) j++; 18 Next[i]=j; 19 } 20 } 21 int KMP( char str[],char ptr[]){ 22 int len1 = strlen(str); 23 int len2 = strlen(ptr); 24 int cnt=0; //cnt记录成功匹配次数 25 getNext(ptr,len2); 26 for(int i=0,j=0;i<len1;i++){ 27 while(j && str[i]!=ptr[j]) j=Next[j-1]; 28 if(str[i]==ptr[j]) j++; 29 if(j == len2){ //匹配到模式串末尾 30 cnt++; 31 j = Next[j-1]; //根据Next数组转移 32 } 33 } 34 return cnt; 35 } 36 37 int main(){ 38 39 std::ios::sync_with_stdio(false); 40 int n;cin>>n; 41 while(n--){ 42 cin>>str1; 43 cin>>str2; 44 int ans = KMP(str2,str1); 45 cout<<ans<<endl; 46 } 47 48 return 0; 49 }