poj 2406 Power Strings

这个就是对next数组的应用了。

比如ababab这个字符串

我的程序的next是-1,0,0,1,2,3,4;
是这么来的
首先定义数组的名字me好了

下面是自己对next的理解,如果有问题,希望能留言指出。对菜菜的我来说是莫大的帮助。。

首先先看:
第一步next[0]==-1 原因在下方
me=sbsbsb;
我们抽出ch=me[0],此时me【0】之前的模式是next【0】==-1,-1因为这个模式下的前缀是不存在的,所以这时候的ch要开拓出一块新的模式,于是next【1】=0;(为何不是-1呢,因为这个模式下,我们有前缀了,是a,我们期望有东西和me【0】匹配)

现在抽出ch=me【1】,此时me【1】之前的模式是next【1】=0(期望匹配me【0】),此时,说明在这之前的模式中存在前缀(是a),ch==b ,不匹配,于是ch不能接上next【1】模式,于是要就去找next【1】之前的模式,然后,这时第一步开始了。。 next【2】=0;然而此时要注意的是(这个模式下的前缀是ab,因为没有me【0】,就谈不上有me【1】 )

这时候next是-1,0(1),0(2);之所以命名为0,是因为这个模式所期望匹配的是(a【0】)
其中模式0有2个,但是2个模式的前缀不同,此时可以看出来0(1)模式的前缀是0(2)模式前缀的前缀。。所以虽然模式都是0,但是相比之下我们首先要判断0(1)模式。可以说,模式0的代表就是0(1)。

现在抽出ch=me【2】,此时me【2】的前一种状态是next【2】=0(期望匹配a【0】);此时此时模式0所代表的模式(a)的前缀(a)和ch一样,此时a满足了0模式,所以这个状态既满足了next【2】=0(前一种状态),又满足了ch==0模式,所以新的模式产生了,定义为1模式(之所以命名为1模式,因为这个模式下所期望匹配的是me【1】,因为前一位ch已经与me【0】匹配了。)

然后抽出ch=me【3】,此时me【3】的前一种状态是next【3】=1;
此时我们期望ch和me【1】匹配,成功了,此时我们把这个状态命名为2模式,因为前前位的ch和0模式,前一位的ch和1模式都已经匹配好了,我们期望下一个ch和me【2】匹配。

然后ch=me【4】,此时me【4】前一种状态是next【4】=2。。。。。
于是重复上面的,得到了next -1,0,0,1,2,3,4。。

如果me=sbsbwsb
首先老样子next=-1,0,0,1,2;
然后ch=me【4】,此时me【4】的前一个状态next【4】==2,这样发现w不和me【2】==s匹配啊。。 这不仅说明2模式再此时不能延续了,还说明和ch匹配的东西在me【2】的前面,而me【2】的前一个模式是next【2】==0,说明如果ch和me【0】一样的话将继承0模式,产生模式1(1)。但是,很可惜失败了me【0】==s,于是开拓出一块新的模式0(3)模式。
于是就有了-1,0,0,1,2,0;

后面一样啦。。

于是发现next【i】就是me【i】所期望匹配的模式号。。可以用next来找到我所期望匹配的模式。。而且模式号就是当前已经匹配的位数。。所以,我们很快就找到了我们希望匹配的字母在me中的位置。。

之所以一开始定义-1,是为了方便,仅此而已。。//弱弱的我是这么认为的

next到此结束。。

于是,当me是由重复的字串构成的时候,我们可以知道next【最后一位】就是重复字串的长度*(重复次数-1)为何减1呢。。 看看next开头那么多0就知道了。。 于是题目就解决了。。

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
char a[1000010];
int next[1000010];
int main()
{
    while(scanf("%s",a)==1)
    {
        int len=strlen(a);
        if(len==1&&a[0]=='.')
            break;
        next[0]=-1;
        int i=0;
        int j=next[0];
        while(i<len)
        {
            if(j==-1||a[i]==a[j])
            {
                i++;
                j++;
                next[i]=j;
            }
            else
            {
                j=next[j];
            }
        }
        if(len%(len-next[len])==0)
            cout<<len/(len-next[len])<<endl;
        else
            cout<<"1"<<endl;
    }
    return 0;
}

你可能感兴趣的:(KMP,poj)