您的位置:首页 > 其它

kmp算法巩固 以poj3461为试验

2013-08-28 22:41 253 查看
本来计划下一步去搞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=
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: