标签:
首先第一题
戳我穿越;http://acm.hdu.edu.cn/showproblem.php?pid=1686
题目大意好理解,每组输入一个子串和一个母串,问在母串中有多少个子串?
文明人不要暴力,因为宽度会超时,除去暴力后这就是赤果果的KMP
KMP的重点在于在子串中建立一个匹配表,记录 到每一位的 前缀后缀 中的相同的子子串的最大长度
然后在比较子母串的时候当遇到不同时 后移的位数就是前面相同的个数减去对应的匹配表例的数
额 讲的不清不楚 那推荐戳这里:http://kb.cnblogs.com/page/176818/
那这题就是个裸的KMP模板
code 还是很简单的
#include<cstdio>
#include<cstring>
using namespace std;
char cword[10001];
int num[10001];
char mword[1000001];
int main()
{
int t,sum,i,x,j,y;
char temp;
while (~scanf("%d",&t))
{
while (t--)
{
sum=0;
j=-1;i=0;
num[0]=-1;
scanf("%s",cword);
scanf("%s",mword);
x=strlen(cword);
y=strlen(mword);
while (i<x) //num数组就是用来储存匹配表
{
if (j==-1||cword[i]==cword[j])
{
j++;
i++;
if (cword[i]!=cword[j])
num[i]=j;
else
num[i]=num[j];
}
else
j=num[j];
}
i=0;j=0;
while (i<y)
{
if (j==-1||mword[i]==cword[j])
{
i++;
j++;
}
else
j=num[j];
if (j==x)
{
sum++;
j=num[j];
}
}
printf("%d\n",sum);
}
}
return 0;
}
第二题 :pid=124http://acm.hdu.edu.cn/showproblem.php?7
输出一个单词里字串的个数
也是kmp的应用,考虑有特殊情况
code更短
#include<cstdio>
#include<cstring>
using namespace std;
char yj[1000001];
int jjc[1000001];
int main()
{
int i,j,x,n;
while (~scanf("%s",yj))
{
if (yj[0]==‘.‘)
break;
j=-1;
jjc[0]=-1;
x=strlen(yj);
for (i=0;i<x;)
{
if (j==-1||yj[i]==yj[j]) jjc[++i]=++j;
else j=jjc[j];
}
if (x%(x-jjc[x])==0)
printf("%d\n",x/(x-jjc[x]));
else
printf("1\n");
}
return 0;
}
第三题:http://poj.org/problem?id=2752
就是找出一行名字中在前缀后缀中都存在的字串的长度,升序输出
对num数组匹配表的运用,既然在前缀后缀中都存在,那么其字串的最后一个字母必定和整个串的最后一位相同
然后再利用num数组一直向下滚一边
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char yj[400001];
int num[400001];
int jjc[400001];
int main()
{
int i,j,x,t,k;
while (~scanf("%s",yj))
{
j=-1;i=0;
num[0]=-1;
x=strlen(yj);
while (i<x)
{
if (j==-1||yj[i]==yj[j])
num[++i]=++j;
else
j=num[j];
}
t=num[x-1];
k=0;
while (t!=-1)
{
if (yj[t]==yj[x-1])
jjc[k++]=t+1;
t=num[t];
}
for (i=k-1;i>=0;i--)
printf("%d ",jjc[i]);
printf("%d\n",x);
}
return 0;
}
hdu 1686 & poj 2406 & poj 2752 (KMP入门三弹连发)
标签:
原文地址:http://www.cnblogs.com/JJCHEHEDA/p/4690262.html