I am coming!KMP!
(中二完毕)
1711:
建议数组用pre命名而不是next,next是c++的关键字
问一个串是否在另一个串中出现过,如出现输出最小出现位置,上模板
--
#include <iostream> #include <math.h> #include <string.h> #include <vector> #include <map> #include <queue> #include <stdio.h> #include <algorithm> #include <cstdio> using namespace std; int pre[1000009],t[1000009],s[1000009]; int main() { int T,n,m; cin>>T; while(T--) { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>t[i]; } for(int i=1;i<=m;i++) { cin>>s[i]; } pre[0]=0; pre[1]=0; int k=0; for(int i=2;i<=m;i++) { while(k&&s[i]!=s[k+1]) k=pre[k]; if(s[i]==s[k+1]) k++; pre[i]=k; } int ok=1; k=0; for(int i=1;ok&&i<=n;i++) { while(k&&t[i]!=s[k+1]) { k=pre[k]; } if(t[i]==s[k+1]) k++; if(k==m) { ok=0; printf("%d\n",i-m+1); } // cout<<i<<" "<<k<<endl; } if(ok) cout<<-ok<<endl; } }
hdu 1686
问s串是否在t串中出现过,求次数,允许重叠。
每次k能匹配到strlen(s)时,num++即可;
#include <iostream> #include <math.h> #include <string.h> #include <vector> #include <map> #include <queue> #include <stdio.h> #include <algorithm> #include <cstdio> using namespace std; int pre[1000009]; char s[1000009],t[1000009]; int main() { int T,n,m; scanf("%d",&T); while(T--) { scanf("%s",s+1); scanf("%s",t+1); pre[0]=0; pre[1]=0; int k=0; for(int i=2;i<=strlen(s+1);i++) { while(k&&s[i]!=s[k+1]) k=pre[k]; if(s[i]==s[k+1]) k++; pre[i]=k; } k=0; int num=0; for(int i=1;i<=strlen(t+1);i++) { while(k&&t[i]!=s[k+1]) k=pre[k]; if(t[i]==s[k+1]) k++; if(k==strlen(s+1)) num++; // cout<<i<<" "<<k<<endl; } printf("%d\n",num); } }
--
hdu 2087
同上,问出现次数,但不同的是不允许重叠,记录每次出现的位置,最后统计答案时声明一指针,如果ans[i]的起点仍在该指针管辖范围内,就不统计,否则令指针=i,保证不重叠。
虽然说狠狠地暴力一通也能过啦。
#include <iostream> #include <math.h> #include <string.h> #include <vector> #include <map> #include <queue> #include <stdio.h> #include <algorithm> #include <cstdio> using namespace std; int pre[1000009],ans[1000009]; char s[1000009],t[1000009]; int main() { int T,n,m; while(1) { scanf("%s%s",t+1,s+1); if(t[1]=='#') break; pre[0]=0; pre[1]=0; int k=0; for(int i=2;i<=strlen(s+1);i++) { while(k&&s[i]!=s[k+1]) k=pre[k]; if(s[i]==s[k+1]) k++; pre[i]=k; } k=0; int num=0; for(int i=1;i<=strlen(t+1);i++) { while(k&&t[i]!=s[k+1]) k=pre[k]; if(t[i]==s[k+1]) k++; if(k==strlen(s+1)) { num++; ans[num]=i-strlen(s+1)+1; } } if(num==0) { printf("0\n"); continue; } int j=1,cnt=1; for(int i=2;i<=num;i++) { if(ans[i]<=ans[j]+strlen(s+1)-1) continue; cnt++; j=i; } printf("%d\n",cnt); } }