其他分享
首页 > 其他分享> > [NOI2014] 动物园 (kmp)

[NOI2014] 动物园 (kmp)

作者:互联网

题面 

浅讲一下思路

1、最开始呢,并没有意识到问题的严重性。认为num与nxt是一样的,再加上一个不重叠的条件即可。然后就发现样例都过不去,还觉得自己可对了。再次读题发现num是字符串的数量,于是又加上了nxt

inline void get_nxt(const string s){
    int j=0;nxt[0]=num[0]=0;
    for(int i=1;i<len;++i){
        while(j&&(s[i]!=s[j]||j>(i+1)/2-1))  j=nxt[j-1];
        cout<<j<<endl;
        if(s[i]==s[j]&&j<(i+1)/2)  num[i]=num[++j]+1;
        nxt[i]=j;
    }
}

当然会wa,为什么呢?num其实只存了对于当前i不重叠的子串,然后就向后转移了。But,当前重叠不代表以后还重叠,因此num并不是单纯的线性关系

2、接下来抱着无奈的心情,直接暴力寻找nxt的“层数”。那么为什么公共前后缀的个数就是nxt的“层数”呢?其证明与nxt相似

(手残见谅)

看得出num【i】=3,那这个3怎么来的?

首先找到第一个nxt[j]<=(i+1)/2,j=3,所以A=B,这是第一个串‘aaa’。继续向前找,nxt【2】也符合条件(其实从此刻向前所有nxt都符合),由A=B得C=D,由nxt【2】=2得C=E,因此E=D,这是第二个串‘aa’。同理可得第三个串‘a’。

inline void get_nxt(const string s){
    int j=0;nxt[0]=0;
    for(int i=1;i<len;++i){
        while(j&&s[i]!=s[j])  j=nxt[j-1];
        if(s[i]==s[j])  ++j;
        nxt[i]=j;int k=j;
        while(k){
            if(k<=(i+1)/2)  num[i]++;
            k=nxt[k-1];
        }
    }
}

十分不出意外,T掉了。因为无法存储num,我们陷入僵局

3、老师让把这道题当例题看,赶紧滚去看了题解,惊讶的发现num可以分开存储和查询

关键来了

如2步中,找到第一个nxt[j]<=(i+1)/2后,所有j=nxt【j-1】都符合。那我们就可以学着kmp,减少重复的搜索。

初始化num【0】=1,表示‘a’是他自己的公共前后缀,也表示此刻为nxt第一层。显然,num【i】并不为前i个字符构成的子串不重复的公共前后缀的个数。那怎么找个数呢?

仍然是找第一个j<=(i+1)/2,但此时num【j-1】,也就是nxt【j】的层数,就是我们所求

上代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,len,j,nxt[1000010],num[1000010];
string s;long long ans;
inline void get_nxt(const string s){
    j=0;num[0]=1;
    for(int i=1;i<len;++i){
        while(j&&s[i]!=s[j])  j=nxt[j-1];
        if(s[i]==s[j])  ++j;
        nxt[i]=j;num[i]=num[j-1]+1;
    }
}
int main()
{
    cin>>n;
    while(n--){
        cin>>s;ans=1;
        len=s.size();get_nxt(s);
        for(int i=0;i<len;++i){
            j=nxt[i];
            while((j<<1)>i+1)  j=nxt[j-1];
            ans=ans*(num[j-1]+1)%mod;
        }
        cout<<ans<<endl;
    }
}

另外,num【j-1】中j可能为0,j-1会越数组下标,O2会爆0。当然,不建议这样写。其实是我懒得改了

 

标签:nxt,const,string,get,int,NOI2014,num,kmp,动物园
来源: https://www.cnblogs.com/yswn/p/16518978.html