终于搞懂KMP了!QAQ
教材:KMP字符串匹配算法2_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
然后根据自己的理解写的代码↓
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 const int MAXN=1000007; 6 char s[MAXN],t[MAXN]; 7 int nxt[MAXN]; 8 int main() 9 { 10 cin>>s>>t; 11 int lens=strlen(s),lent=strlen(t); 12 //make_nxt 13 int len=0; 14 int i=1; 15 nxt[0]=0; 16 while(i<lent){ 17 if(t[i]==t[len]){ 18 len++; 19 nxt[i]=len; 20 i++; 21 } 22 else{ 23 if(len){ 24 len=nxt[len-1]; 25 } 26 else{ 27 nxt[i]=0; 28 i++; 29 } 30 } 31 } 32 //move_nxt 33 for(int i=lent;i;--i) 34 nxt[i]=nxt[i-1]; 35 nxt[0]=-1; 36 //search 37 int j=0; 38 i=0; 39 while(i<lens){ 40 if(j==lent-1){ 41 if(s[i]==t[j]){ 42 cout<<i-j+1<<endl; 43 j=nxt[j]; 44 } 45 } 46 if(s[i]==t[j]){ 47 i++;j++; 48 } 49 else{ 50 if(j!=-1){ 51 j=nxt[j]; 52 } 53 else{ 54 i++;j++; 55 } 56 } 57 } 58 //print 59 for(int i=1;i<=lent;++i) 60 cout<<nxt[i]<<" "; 61 return 0; 62 }
以及 这个代码确实很不优
以前从网上抄的但根本写不出来的快很多的代码↓
#include<iostream> #include<cstring> #include<cstdio> using namespace std; char s1[1000007]; char s2[1000007]; int nex[1000007]; int main() { //freopen("a.in","r",stdin); scanf("%s %s",&s1,&s2); int p,k,i,j,len1=strlen(s1),len2=strlen(s2); k=-1; nex[0]=-1; for(p=1;p<len2;++p) { while(k>-1&&s2[k+1]!=s2[p])k=nex[k]; if(s2[k+1]==s2[p])k++; nex[p]=k; } k=-1; for(p=0;p<len1;++p) { while(k>-1&&s2[k+1]!=s1[p])k=nex[k]; if(s2[k+1]==s1[p])k++; if(k==len2-1){printf("%d ",p-len2+2);k=-1;p=p-len2+1;} } for(i=0;i<len2;++i) printf("%d ",nex[i]+1); return 0; }
其实里面的思路都差不多,但是在模板题「LuoguP3375」【模板】KMP字符串匹配 上测,有差不多翻倍的时间差距。
不过用for这样搞确实没有while好想好打(逃
18.10.6 UPD:
今天考试 有30分给的KMP
我硬是没想起来自己理解的超长代码,随手背出了网上抄的那个
真香