题意:给出几组数据,每组有字符串W和T,问你W在T中出现几次。
思路:字符串长度很大,用KMP算法。
一开始写的是:调用KMP算法查找W在T中是否匹配,若匹配,则个数+1。则接下来T的索引移动相应的距离,再调用函数判断T接下来的序列中是否存在W。
如果不能匹配,则终止。
结果,这样超时了。。。估计是调用函数上面花费了些时间。
后来直接在函数中记录出现的个数,这样就不超时了。
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int maxT=1000010; const int maxW=10010; char w[maxW],t[maxT]; int suffix[maxW];//suffix[i]=k:表示P中前i个字符中,后缀与前缀间的最长匹配子串的长度。 void dealSuffix(int m){ memset(suffix,0,sizeof(suffix)); suffix[0]=-1; suffix[1]=0; int k=0; for(int i=2;i<=m;i++){ while(k>=0 && w[k]!=w[i-1]) k=suffix[k]; suffix[i]=++k; } } //m为W字符串的长度 int match(int n,int m){ int i=0,j=0; //i为T中字符的下标,j为W中字符的下标 int cnt=0; //统计W字符串在T字符串中出现的次数 while(i<=n-1){ if(j<0){ i++; j=0; } if(t[i]==w[j]){ i++; j++; } else if(j>=0){ j=suffix[j]; //当j=0的时候,suffix[0]=-1,这样j就会小于0,所以一开始有判断j是否小于0 } //W在T中找到匹配 if(j==m){ cnt++; j=suffix[j]; } } return cnt; } int main() { int n,lw,lt; scanf("%d",&n); getchar(); //用gets的话,这里要写个getchar() while(n--){ gets(w); gets(t); lw=strlen(w); //W字符串的长度 lt=strlen(t); //T字符串的长度 dealSuffix(lw); int ans=match(lt,lw); printf("%d ",ans); } return 0; }
下面是照搬算法导论上的代码:
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int maxT=1000010; const int maxW=10010; char w[maxW],t[maxT]; int suffix[maxW];//suffix[i]=k:表示P中前i个字符中,后缀与前缀间的最长匹配子串的长度。 //m为w字符串的长度 void getSuffix(int m){ memset(suffix,0,sizeof(suffix)); suffix[1]=0; int k=0; for(int i=2;i<=m;i++){ while(k>0 && w[k]!=w[i-1]) k=suffix[k]; if(w[k]==w[i-1]) k++; suffix[i]=k; } } //n为t字符串的长度,m为W字符串的长度 int match(int n,int m){ int k=0,ans=0; for(int i=0;i<n;i++){ while(k>0 && w[k]!=t[i]) k=suffix[k]; if(w[k]==t[i]) k++; if(k==m){ ans++; k=suffix[k]; } } return ans; } int main() { int n,lw,lt; scanf("%d",&n); getchar(); //用gets的话,这里要写个getchar() while(n--){ gets(w); gets(t); lw=strlen(w); //W字符串的长度 lt=strlen(t); //T字符串的长度 getSuffix(lw); int ans=match(lt,lw); printf("%d ",ans); } return 0; }