ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2014] 动物园 (kmp)

2022-07-25 22:04:36  阅读:149  来源: 互联网

标签:nxt const string get int NOI2014 num 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有