hdu2087(kmp)

题意:

给定一个文本串s和一个模式串p,找出模式串在文本串中出现的次数。注意:模式串在文本串中出现的位置不能重叠


当然本题不用kmp算法也能通过,借用本题回忆一下kmp算法。

kmp算法要用到一个数组记录一下信息,此数组取名为next[],现在说一下next数组的含义:

next[i] 表示模式串p的前i个 字符组成的前缀这个字符串的前缀后缀能匹配的最大值k。(k<i)

        解释一下字符串前缀和后缀:

假设字符串string为 a1a2a3.....an(字符串的长度为n)

       string的前缀是这样的字符串:        a1a2.....ai     (1<=i<=n)

       string的后缀是这样的字符串:      ai..........an     (1<=i<=n)        

例如    abcabc这个字符串的前缀和后缀能匹配的最大值是3

next数组的作用就是当模式串和文本串匹配到某个位置,在此位置之后的字符不能匹配时,next数组指明了模式串应跳到某个位置继续和文本串继续匹配

   

根据模式串求next数组的函数
// next[i-1]是字符串a1a2....a(i-1)的前缀和后缀匹配的最大值,为了方便令 k = next[i-1],如果a(k+1)== a[i],那么next[i] = k+1,否则令k = next[k],继续循环,直到 k==0 或者 p[k+1] == p[i]
	void getnext(char* p)   //p是模式串
	{
   		next[1] = 0;
    		int k = 0;       
   		for(int i=2;i<=lenp;i++)  //k的值为next[i-1],根据以前求得的next值求next[i]
    		{
        		while(k!=0 && p[k+1] != p[i])
            			k = next[k];
        		if(p[k+1] == p[i]) k++;
        		next[i] = k;
    		}
	}
kmp函数
void kmp(char* p, char* s)
{
    getnext(p);//求得next数组
    int q = 0;  //q表示模式串p和文本串s当前匹配的个数,初始化为0
    for(int i=1;i<=lens;i++)
    {
        while(q!=0 && p[q+1] != s[i])
            q = next[q];
        if(p[q+1] == s[i]) q++;
        if(q == lenp)
        {
            //此时模式串已经在文本串中出现过
        }
    }
}


hdu2087代码:
#include <cstdio>
#include <cstring>


const int maxn = 1005;
char p[maxn], s[maxn];
int lenp,lens,cnt;
int next[maxn];
void getnext(char* p)
{
    next[1] = 0;
    int k = 0;
    for(int i=2;i<=lenp;i++)
    {
        while(k!=0 && p[k+1] != p[i])
            k = next[k];
        if(p[k+1] == p[i]) k++;
        next[i] = k;
    }
}
void kmp(char* p, char* s)
{
    getnext(p);//求得next数组
    int q = 0;  //q表示模式串p和文本串s当前匹配的个数,初始化为0
    for(int i=1;i<=lens;i++)
    {
        while(q!=0 && p[q+1] != s[i])
            q = next[q];
        if(p[q+1] == s[i]) q++;
        if(q == lenp)
        {
            cnt++;
            q = 0;
        }
    }
}
int main()
{
    while(scanf("%s",s+1)!=EOF && s[1] != '#')
    {
        scanf("%s",p+1);
        lens = strlen(s+1);
        lenp = strlen(p+1);
        cnt = 0;
        kmp(p,s);
        printf("%d\n",cnt);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值