感觉大概已经了解到KMP算法了,就去搜索POJ上面的水题来练习一下,找找感觉!一找就发现问题了!我对KMP算法还没有领悟进入!
我开始的代码是这样写的:
- #include<stdio.h>
- #include<string.h>
- #define MT 1000005
- #define MP 10005
- char t[MT],p[MP];
- int t_len,p_len;
- int next[MP];//next又可以看作从前缀的末尾往前数数的个数
- void cal_next(char *p){
- int index,i;
- next[0]=-1;
- for(i=1;p[i]!=0;i++){
- index=next[i-1];
- while(index>-1&&p[index+1]!=p[i]){
- index=next[index];
- }
- if(p[index+1]==p[i]){
- next[i]=index+1;
- }else{
- next[i]=-1;
- }
- }
- }
- int KMP(char *t,char *p){
- int i,j;
- if(t_len<p_len)return -1;
- i=j=0;
- while(t[i]!=0&&p[j]!=0){
- if(t[i]==p[j]){
- i++,j++;
- }else if(j==0){
- i++;
- } else{
- j=next[j-1]+1;//这里 i不再回退了,而随着i不再回退,j也不归零了!
- }
- }
- if(p[j]==0){
- return i-j;
- }
- return -1;
- }
- int main(){
- int ti;
- char *t_p;
- scanf("%d",&ti);
- while(ti--){
- int pos,ans;
- scanf("%s %s",p,t);
- p_len=strlen(p);
- t_len=strlen(t);
- ans=0;t_p=t;
- cal_next(p);//与普通匹配相比,多了计算next数组的一行代码
- pos=KMP(t_p,p);
- while(pos!=-1){
- ans++;
- t_p=t_p+pos+1;
- pos=KMP(t_p,p);
- }
- printf("%d\n",ans);
- }
- return 0;
- }
但是这个代码提交上去一直TLE,后面在网上找到了这个代码:
- #include<stdio.h>
- #include<string.h>
- #define MT 1000005
- #define MP 10005
- char t[MT]="",p[MP]="";
- int next[MP];//next又可以看作从前缀的末尾往前数数的个数
- void cal_next(char *p,int len){
- int i,j;
- j=next[0]=-1;
- for(i=1;i<len;i++)
- {
- while(j!=-1&&p[i]!=p[j+1])j=next[j];
- if(p[j+1]==p[i])j++;
- next[i]=j;
- }
- }
- int KMP(char *t,char *p){
- int i,j,sum;
- int t_len=strlen(t);
- int p_len=strlen(p);
- cal_next(p,p_len);
- for(i=0,j=-1,sum=0;i<t_len;i++)
- {
- while(j!=-1&&p[j+1]!=t[i])j=next[j];
- if(p[j+1]==t[i])j++;
- if(j==p_len-1)
- {
- sum++;
- j=next[j];
- }
- }
- return sum;
- }
- int main(){
- int ti;
- scanf("%d",&ti);
- while(ti--){
- scanf(" %s %s",p,t);
- printf("%d\n",KMP(t,p));
- }
- return 0;
- }
看到这段代码,我才对KMP算法的学习又深入了一点!由于刚开始学习KMP算法,我们是一个匹配的例子开始的,结果我就陷入了匹配的怪圈,即KMP算法是用于字符串匹配的,匹配到或者找遍整个字符串就完了!但是我们通常用文本编辑器也能看到,字符串匹配的时候是找到所有的能匹配的字符串,而不仅仅是只找到第一个就Game Over了!找到第一个字符串就匹配完成是我自己的一厢情愿,而不是KMP的本意!看到上面这题应该就有这样的理解!