ICode9

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

P2375 [NOI2014]动物园 KMP

2019-06-15 19:03:06  阅读:180  来源: 互联网

标签:nxt ch P2375 ans long NOI2014 KMP include define


好,暴力能拿$50pts\space qwq$


 

暴力的思路就是一直跳$nxt[j]$,直到它的长度小于串的一半,然后开始计数,当然要接着跳$nxt[j]$

正解:考虑没有长度要求的(不要求不重合)公共前后缀的数目,显然$ans[i]=ans[j]+1$相当于$i$比$j$是多了$i$它本身。

所以求解时模仿$kmp$的过程,$num[i]$就是一直跳$nxt[j]$,然后直到$j<=\frac{i}{2}$,$num[i]=ans[j]$

注意,此处模仿$kmp$的原因是,能够避免跳过一些冗余的$nxt[j]$($nxt[j]$过大的情况),对于下一次匹配,上一次的$j$就是上一次的小于等于$\frac{i}{2}$的最长公共前后缀的长度,如果还能匹配就直接匹配,过长了再跳一下$nxt[j]$,否则就一直跳$nxt[j]$,直到匹配。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ull unsigned long long
#define ll long long
#define R register int
#define pause for(R i=1;i<=10000000000;++i)
using namespace std;
namespace Fread {
    static char B[1<<15],*S=B,*D=B;
    #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    } inline bool isempty(const char& ch) {return ch<=36||ch>=127;}
    inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
}using Fread::g; using Fread::gs;
const int M=1000000007;
int n,nxt[1000010],ans[1000010]; char s[1000010]; ll num=1;
inline void PRE() { nxt[1]=0;
    for(R i=2,j=0;i<=n;++i) { 
        while(j&&s[i]!=s[j+1]) j=nxt[j];
        if(s[i]==s[j+1]) ++j; nxt[i]=j;
        ans[i]=ans[j]+1; 
    }
}
inline void calc() {
    for(R i=2,j=0;i<=n;++i) {
        while(j&&s[i]!=s[j+1]) j=nxt[j];
        if(s[i]==s[j+1]) ++j; 
        while(j>i/2) j=nxt[j];
        (num*=(ans[j]+1))%=M;
    }
}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif
    R t=g(); for(R i=1;i<=t;++i) { memset(s,0,sizeof(s)); num=1;
        gs(s+1); n=strlen(s+1);  ans[1]=1; PRE();
//        for(R i=2;i<=n;++i) { R lim=i/2,j=i,cnt=0;
//            while(j) {j=nxt[j]; if(j&&j<=lim) ++cnt;}
//            (ans*=(cnt+1))%=M; 
//        } 
        calc();
        printf("%lld\n",num);
    } 
}

2019.06.15

 

标签:nxt,ch,P2375,ans,long,NOI2014,KMP,include,define
来源: https://www.cnblogs.com/Jackpei/p/11028492.html

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

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

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

ICode9版权所有