BZOJ 3670 NOI2014 动物园 KMP+dp

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3670

题意概述:令num[i]表示字符串由1~i的字符形成的前缀中不相重叠的相同前后缀的数量,求mul{ num[i] | 1<=i<=L }mod1000000007。

实际上只要对KMP理解的好这就是个水题,可以想到dp求得num数组,num[i]=num[f[i]]+1,f[i]表示字符串的前缀1~i形成的不重叠的最长相同前后缀长度,如果f[i]的话就不存在。题目的提醒实际上很明显,想想KMP,发现这个也是一个用失配函数来匹配自己的过程。在推算f[i+1]的时候,先令j=f[i],这样做直接保证了长度限制,并且如果可以匹配成功一定是最优的。然后在fail函数上匹配,直到成功为止。这个时候j后移一位,判断一下长度限制,如果不符合在fail上面再回跳一次。

主要是用到了fail函数一种理解方式:f[i]表示的是前i个字符最长相同前后缀长度。(这个前后缀是不包括原串的)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 const int maxn=1000005;
14 const int mo=1000000007;
15
16 int N,f1[maxn],f2[maxn],h[maxn];
17 char S[maxn];
18
19 void getfail(char *p)
20 {
21     int m=strlen(p);
22     f1[0]=f1[1]=0;
23     for(int i=1;i<m;i++){
24         int j=f1[i];
25         while(j&&p[j]!=p[i]) j=f1[j];
26         f1[i+1]=p[j]==p[i]?j+1:0;
27     }
28     f2[0]=f2[1]=0;
29     for(int i=1;i<m;i++){
30         int j=f2[i];
31         while(j&&(p[j]!=p[i])) j=f1[j];
32         if(p[j]==p[i]) j++;
33         if(j*2>i+1) j=f1[j];
34         f2[i+1]=j;
35     }
36 }
37 int main()
38 {
39     scanf("%d\n",&N);
40     for(int i=1;i<=N;i++){
41         gets(S); getfail(S);
42         int n=strlen(S);
43         h[1]=0;
44         for(int i=2;i<=n;i++) h[i]=h[f1[i]]+(f1[i]?1:0);
45         int ans=1;
46         for(int i=1;i<=n;i++) ans=(1ll*ans*(h[f2[i]]+(f2[i]?1:0)+1))%mo;
47         printf("%d\n",ans);
48     }
49     return 0;
50 }

原文地址:https://www.cnblogs.com/KKKorange/p/8505454.html

时间: 2024-10-10 05:20:12

BZOJ 3670 NOI2014 动物园 KMP+dp的相关文章

BZOJ 3670 NOI2014 动物园 KMP算法

题意: 给定一个长为L的字符串(L<=100W),求一个num数组,num[i]表示长度为i的前缀中字符串S'的数量,其中S'既是该前缀的前缀也是该前缀的后缀,且|S'|*2<=i 求Π(num[i]+1)%1000000007 这就是KMP算法的一个变形...首先求出next数组,顺便求出cnt数组,代表长度为i的前缀经过几次fix=next[fix]会得到0,然后重新匹配一次,这次注意当fix*2>i的时候令fix=next[fix]即可 这题有坑 切忌用num数组代替next 此外

bzoj 3670: [Noi2014]动物园

Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:"对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数组的含义吗?" 熊猫:"对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度

【BZOJ】3670: [Noi2014]动物园

http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意:太水了= = #include <bits/stdc++.h> using namespace std; const int N=1000005, mo=1000000007; int n, p[N], pos[N], num[N], tot; char s[N]; bool vis[N]; void dfs(int x) { if(p[x]) dfs(p[x]); vis[x]=1

NOI2014 动物园

3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 174  Solved: 92[Submit][Status] Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)

【bzoj3670】[Noi2014]动物园

3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2080  Solved: 1107[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:"对于一个字符串S,它的长度

BZOJ 3670 &amp;&amp; BZOJ 3620 &amp;&amp; BZOJ 3942 KMP

最近感到KMP不会啊,以前都是背板的现在要理解了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int Maxn=16000; 7 8 char S[Maxn]; 9 int k,P[Maxn],Ans; 10 11 12 inline void Kmp(char * S

Luogu P2375 动物园 kmp

P2375 动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数组的含义吗?” 熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[

bzoj3670[Noi2014]动物园

bzoj3670[Noi2014]动物园 题意: 对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i].给出字符串S求所有num[i]+1的乘积模1000000007.字符串长度≤1000000 题解: 先求一遍fail函数,得到数组记为next1,然后再求next2数组,表示满足next1[j]*2≤i的next1[j],这一过程也是可以递推的.同时用cnt数组记录next1[j]有多少个.num[i]就是cnt[nex

codeforces432D Prefixes and Suffixes(kmp+dp)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud D. Prefixes and Suffixes You have a string s = s1s2...s|s|, where |s| is the length of string s, and si its i-th character. Let's introduce several definitions: A substring s[i..j] (1 ≤ i ≤ j