hdu1711 + hdu1686 + hdu2087 kmp入门
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);
}
}