zoukankan      html  css  js  c++  java
  • 【BZOJ3670】[NOI2014] 动物园(KMP)

    点此看题面

    大致题意: 定义(num_i)为一个长度为(n)的字符串前(i)个字符构成的子串中同时是其后缀和前缀该后缀和前缀不重叠的字符串个数,求(prod_{i=1}^n(num_i+1))

    (KMP)

    首先,让我们不考虑后缀和前缀不重叠这个限制。

    则满足条件的字符串,显然就是(nxt_i,nxt_{nxt_i},nxt_{nxt_{nxt_i}}......)

    如果我们设这样的字符串有(f_i)个,则显然我们可以在求(nxt)数组的同时,递推得到(f)数组。(只要在(nxt_i=j)这句话之后加上(f_i=f_{nxt_i}+1)即可)

    然后我们考虑加上这个限制后,其实就是求出最大的(j),满足(j=nxt_{..._{nxt_i}}),且(2 imes jle i),然后(num_i)就等于(f_j)

    至于如何在枚举(i)的时候维护这个(j),只要以类似于求(nxt)数组的方法,并强制(2 imes jle i)即可。

    具体实现详见代码。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    #define X 1000000007
    using namespace std;
    int n,nxt[N+5],f[N+5];char s[N+5];
    I void GetNxt()//求nxt数组
    {
    	RI i,j;for(i=2,j=nxt[1]=0,f[1]=1;i<=n;++i)
    	{
    		W(j&&s[j+1]^s[i]) j=nxt[j];s[j+1]==s[i]&&++j,
    		f[i]=f[nxt[i]=j]+1;//同时求出f数组
    	}
    }
    I void GetAns()//求答案
    {
    	RI i,j,t=1;for(i=2,j=0;i<=n;++i)
    	{
    		W(j&&s[j+1]^s[i]) j=nxt[j];s[j+1]==s[i]&&++j;
    		W(2*j>i) j=nxt[j];t=1LL*t*(f[j]+1)%X;//强制2*j<=i
    	}printf("%d
    ",t);
    }
    int main()
    {
    	RI Tt;scanf("%d",&Tt);W(Tt--) scanf("%s",s+1),n=strlen(s+1),GetNxt(),GetAns();
    	return 0;
    }
    
  • 相关阅读:
    android KK版本号,如何更改蓝牙设备类型
    C# DataTable的詳細使用方法
    JAVA进阶-注解
    Android -- Looper.prepare()和Looper.loop() —深入版
    Java面试宝典2013版(超长版)
    HttpClient使用具体解释
    中间件
    Java笔试题集锦
    BDB (Berkeley DB)数据库简单介绍(转载)
    struts2 通配符简化配置
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3670.html
Copyright © 2011-2022 走看看