zoukankan      html  css  js  c++  java
  • BZOJ 3670: [Noi2014]动物园

    现在看来真是自然无比。。。

    首先我们先求出(next)数组,然后不考虑那个不重叠的限制

    换句话说现在可以搞一个(num')出来,容易发现对于一个前缀(i)(next_i)它满足题目的要求,同时(next_{next_i})显然也是满足的,再往下推同理

    然后我们发现(num')数组可以和(next)数组一起递推出来,非常方便,那么现在就是怎么求(num)的问题了

    随手画个图,假设我们现在对于位置(i)(next)向前跳,直到跳到第一个位置(j)满足(jlelfloor frac{i}{2} floor),那么这个时候应该是这样:

    此时显然从(j)开始往前跳(next)的串都满足要求,并且(num'_j=num_i)(因为不会重复了,(j)的前缀已经和(i)的后缀相同)

    然后就做完了,复杂度(O(n))

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1000005,mod=1e9+7;
    char s[N];
    int n,next[N],num[N],ans,t;
    inline void get_next(char *s)
    {
    	register int i; int len=0;
    	for (i=2;i<=n;++i)
    	{
    		while (len&&s[i]!=s[len+1]) len=next[len];
    		if (s[i]==s[len+1]) ++len; next[i]=len; num[i]=num[len]+1;
    	}
    }
    inline void get_num(char *s)
    {
    	register int i; int len=0;
    	for (i=2;i<=n;++i)
    	{
    		while (len&&s[i]!=s[len+1]) len=next[len];
    		if (s[i]==s[len+1]) ++len;
    		while ((len<<1)>i) len=next[len];
    		ans=1LL*ans*(num[len]+1)%mod;
    	}
    }
    int main()
    {
    	scanf("%d",&t); while (t--)
    	{
    		scanf("%s",s+1); n=strlen(s+1); ans=1;
    		memset(next,0,sizeof(next)); num[1]=1;
    		get_next(s); get_num(s); printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    BlogEngine.Net
    加速Web开发的9款知名HTML5框架
    个人论坛博客的代码
    Android客户端调用Asp.net的WebService
    前端总结数据结构与算法基础
    node知识点及第三方模块
    消息轮播
    el-date-picker 组件时间格式化方式
    Vue+Element前端导入导出Excel
    vue单元测试
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12245739.html
Copyright © 2011-2022 走看看