kmp算法巩固 以poj3461为试验

本来计划下一步去搞AC自动机的……忽发现它以KMP为基础……虽然假期练过,但基本内涵都不太清楚了,都是直接套模板Orz……是本次来再补一下(⊙﹏⊙) ,总算把自己的板给写出来了,真是可喜可贺XD

以下先是KMP的重新理解部分:用parent[]表示母串,son[]表示子串

当比较母串和子串时,以abcdefg和bcdf为例

母串: a b  c  d e f g

子串:    b  c  d  f

序号: 0 1 2  3  4

当比较到上面这一步时,可发现son[2]与parent[2]失配。如果是朴素算法,接下来会把子串右移,重新比较,而当比较到第x位时,子串的前x位与对应母串的的前x位相同,所以可以预处理子串的情况,先把子串与子串本身比较,当第x位失配时,子串要右移到第几位为止,这样就不需要每次都右移一位,一个个地试了。把需要右移到第几位的值保存在一个next数组中。我见过的next数组求法都不知道几组了QAQ,而且还难理解,果然要自己来写才行……


以下是今天写的一个模板:

//该模板用来找子串在母串中是否存在,若存在,返回起始点,否则,返回-1
const int maxsize=100010;
struct KMP
{
	char parent[maxsize];int parentlen;
	char son[maxsize];int sonlen;
	int next[maxsize];
	
	void init()
	{
		memset(next, 0, sizeof(next));
		return ;
	}
	void insert()
	{
		scanf("%s", parent);
		parentlen=strlen(parent);
		scanf("%s", son);
		sonlen=strlen(son);
		return ;
	}
	
	void buildnext()
	{
		int pos=2, cnt=0;
		next[0]=-1;next[1]=0;
		while(pos<=sonlen)
		{
			if(son[pos-1]==son[cnt])
				next[pos++]=++cnt;
			else if(cnt>0)
				cnt=next[cnt];
			else
				pos++;
		}
		return ;
	}
	
	int compare()
	{
		int parentcnt=0, soncnt=0;
		while(parentcnt<=parentlen)
		{
			if(parent[parentcnt]==son[soncnt])
			{
				parentcnt++;soncnt++;
			}
			else if(soncnt>0)
					soncnt=next[soncnt];
			else
				parentcnt++;
			if(soncnt==sonlen)
				return parentcnt-soncnt+1;
		}
		return -1;
	}
}kmp;

然后找了道水题试了一下……稍微改下模板就能过了真是太赞!XD

题号是poj 

#include<cstdio>
#include<cstring>
const int maxsize=1000010;
struct KMP
{
	char parent[maxsize];int parentlen;
	char son[maxsize];int sonlen;
	int next[maxsize];
	
	void init()
	{
		memset(next, 0, sizeof(next));
		return ;
	}
	void insert()
	{		
		scanf("%s", son);
		sonlen=strlen(son);
		scanf("%s", parent);
		parentlen=strlen(parent);
		return ;
	}
	
	void buildnext()
	{
		int pos=2, cnt=0;
		next[0]=-1;next[1]=0;next[sonlen]=0;
		while(pos<=sonlen)
		{
			if(son[pos-1]==son[cnt])
				next[pos++]=++cnt;
			else if(cnt>0)
				cnt=next[cnt];
			else
				pos++;
		}
		return ;
	}
	
	int compare()
	{
		int parentcnt=0, soncnt=0;
		int ret=0;
		while(parentcnt<=parentlen)
		{
			if(parent[parentcnt]==son[soncnt])
			{
				parentcnt++;soncnt++;
			}
			else if(soncnt>0)
					soncnt=next[soncnt];
			else
				parentcnt++;
			if(soncnt==sonlen)
				ret++;
		}
		return ret;
	}
}kmp;
int main()
{
	int ncase;
	int ans;
	scanf("%d", &ncase);
	while(ncase--)
	{
		kmp.init();
		kmp.insert();
		kmp.buildnext();
		ans=kmp.compare();
		printf("%d\n", ans);
	}
	return 0;
}

自从trie后就喜欢上用struct了……看起来比较方便QvQ,但是总归得用class比较好吧……下次再想,明天可准备自动机了=w=

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值