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

    Description

    近日,园长发现动物园中好吃懒做的动物越来越多了。例如企鹅,只会卖萌向游客要吃的。为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法。
    某天,园长给动物们讲解KMP算法。
    园长:“对于一个字符串S,它的长度为L。我们可以在O(L)的时间内,求出一个名为next的数组。有谁预习了next数组的含义吗?”
    熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[i]。”
    园长:“非常好!那你能举个例子吗?”
    熊猫:“例S为abcababc,则next[5]=2。因为S的前5个字符为abcab,ab既是它的后缀又是它的前缀,并且找不到一个更长的字符串满足这个性质。同理,还可得出next[1] = next[2] = next[3] = 0,next[4] = next[6] = 1,next[7] = 2,next[8] = 3。”
    园长表扬了认真预习的熊猫同学。随后,他详细讲解了如何在O(L)的时间内求出next数组。
    下课前,园长提出了一个问题:“KMP算法只能求出next数组。我现在希望求出一个更强大num数组一一对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。例如S为aaaaa,则num[4] = 2。这是因为S的前4个字符为aaaa,其中a和aa都满足性质‘既是后缀又是前缀’,同时保证这个后缀与这个前缀不重叠。而aaa虽然满足性质‘既是后缀又是前缀’,但遗憾的是这个后缀与这个前缀重叠了,所以不能计算在内。同理,num[1] = 0,num[2] = num[3] = 1,num[5] = 2。”
    最后,园长给出了奖励条件,第一个做对的同学奖励巧克力一盒。听了这句话,睡了一节课的企鹅立刻就醒过来了!但企鹅并不会做这道题,于是向参观动物园的你寻求帮助。你能否帮助企鹅写一个程序求出num数组呢?
    特别地,为了避免大量的输出,你不需要输出num[i]分别是多少,你只需要输出对1,000,000,007取模的结果即可。

    Solution

    当作自己和自己作匹配就行了
    记录一个 (f[i]) 表示从 (i) 开始跳 (next) ,直到跳到 (0) 的次数
    满足条件的要求是 (i-next+1>next)
    每一次暴力跳即可,因为 (kmp) 复杂度是对的,所以这一题复杂度是对的
    复杂度 (O(n+m))

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+10,mod=1e9+7;
    int n,nxt[N],f[N];char s[N];
    void work(){
    	memset(nxt,0,sizeof(nxt));
    	memset(f,0,sizeof(f));
    	scanf("%s",s+1);
    	n=strlen(s+1);f[1]=1;
    	for(int i=2;i<=n;i++){
    		int p=nxt[i-1];
    		while(p && s[p+1]!=s[i])p=nxt[p];
    		if(s[p+1]==s[i])nxt[i]=p+1,f[i]=f[p+1]+1;
    		else f[i]=1;
    	}
    	int p=0,ans=1;
    	for(int i=1;i<=n;i++){
    		if(s[p+1]!=s[i]){
    			while(p && s[p+1]!=s[i])p=nxt[p];
    			if(s[i]==s[p+1])p++;
    		}
    		else p++;
    		while(p && (p<<1)>=i+1)p=nxt[p];
    		ans=1ll*ans*(f[p]+1)%mod;
    	}
    	cout<<ans<<endl;
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      int T;cin>>T;
      while(T--)work();
      return 0;
    }
    
    
  • 相关阅读:
    2021NUAA暑假集训 Day3 题解
    2021NUAA暑假集训 Day2 题解
    2021NUAA暑期模拟赛部分题解
    CodeForces 1038D Slime
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 10689 Yet another Number Sequence
    HDU 4549 M斐波那契数列
    HDU 4990 Reading comprehension
    CodeForces 450B Jzzhu and Sequences
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8511390.html
Copyright © 2011-2022 走看看