洛谷 P2375 [NOI2014]动物园 解题报告
P2375 [NOI2014]动物园
题目描述
近日,园长发现动物园中好吃懒做的动物越来越多了。例如企鹅,只会卖萌向游客要吃的。为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法。
某天,园长给动物们讲解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]\)分别是多少,你只需要输出所有(\(num[i]+1\))的乘积,对\(1,000,000,007\)取模的结果即可。
输入输出格式
输入格式:
第\(1\)行仅包含一个正整数\(n\) ,表示测试数据的组数。
随后\(n\)行,每行描述一组测试数据。每组测试数据仅含有一个字符串\(S\),\(S\)的定义详见题目描述。数据保证\(S\) 中仅含小写字母。输入文件中不会包含多余的空行,行末不会存在多余的空格。
输出格式:
包含 \(n\) 行,每行描述一组测试数据的答案,答案的顺序应与输入数据的顺序保持一致。对于每组测试数据,仅需要输出一个整数,表示这组测试数据的答案对 \(1,000,000,007\) 取模的结果。输出文件中不应包含多余的空行。
说明
| 测试点编号 | 约定 |
|---|---|
| 1 | \(N ≤ 5, L ≤ 50\) |
| 2 | \(N ≤ 5, L ≤ 200\) |
| 3 | \(N ≤ 5, L ≤ 200\) |
| 4 | \(N ≤ 5, L ≤ 10,000\) |
| 5 | \(N ≤ 5, L ≤ 10,000\) |
| 6 | \(N ≤ 5, L ≤ 100,000\) |
| 7 | \(N ≤ 5, L ≤ 200,000\) |
| 8 | \(N ≤ 5, L ≤ 500,000\) |
| 9 | \(N ≤ 5, L ≤ 1,000,000\) |
| 10 | \(N ≤ 5, L ≤ 1,000,000\) |
首先,如果学过KMP,很容易得到这样一个暴力算法
50pts
#include <cstdio>
#include <cstring>
#define ll long long
const ll mod=1e9+7;
const int N=1e6+10;
char c[N];
int nxt[N],cnt[N],n;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%s",c+1);
int len=strlen(c+1);
ll ans=1;
for(int j=0,i=2,k;i<=len;i++)
{
while(j&&c[j+1]!=c[i])
j=nxt[j];
if(c[j+1]==c[i])
nxt[i]=++j,cnt[i]=cnt[j]+1;
else
cnt[i]=nxt[i]=0;
k=i;
while(nxt[k]<<1>i) k=nxt[k];
(ans*=1ll+cnt[k])%=mod;
}
printf("%lld\n",ans);
}
return 0;
}
我们可以对KMP的nxt数组建图,发现它是一颗树,可以拿倍增跳
80pts
// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#define ll long long
const ll mod=1e9+7;
const int N=1e6+10;
int Next[N<<1],to[N<<1],head[N],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
char c[N];
int nxt[N],Cnt[N],n,s[N],f[N][21],tot;
void dfs(int sta)
{
s[++tot]=sta;
while(tot)
{
int now=s[tot--];
for(int i=head[now];i;i=Next[i])
s[++tot]=to[i],f[to[i]][0]=now;
}
}
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%s",c+1);
memset(head,0,sizeof(head));cnt=0;
int len=strlen(c+1);
ll ans=1;add(0,1);
for(int j=0,i=2;i<=len;i++)
{
while(j&&c[j+1]!=c[i])
j=nxt[j];
if(c[j+1]==c[i])
nxt[i]=++j,Cnt[i]=Cnt[j]+1;
else
Cnt[i]=nxt[i]=0;
add(nxt[i],i);
}
dfs(0);
for(register int j=1;j<=18;j++)
for(register int i=1;i<=len;i++)
f[i][j]=f[f[i][j-1]][j-1];
for(register int i=1;i<=len;i++)
{
int k=i;
for(register int j=18;~j;j--)
if(f[k][j]<<1>i) k=f[k][j];
(ans*=1ll+Cnt[k])%=mod;
}
printf("%lld\n",ans);
}
return 0;
}
这地方其实不需要建图,是我屑了
然后把倍增两维反过来开就A了,好像是因为内存的某些原因所以快一些
正解是先把所有Cnt跑出来
然后再KMP匹配时直接不匹配超过一半就行了
#include <cstdio>
#include <cstring>
#define ll long long
const ll mod=1e9+7;
const int N=1e6+10;
char c[N];
int nxt[N],Cnt[N],n;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%s",c+1);
int len=strlen(c+1);
ll ans=1;Cnt[1]=1;
for(int j=0,i=2;i<=len;i++)
{
while(j&&c[j+1]!=c[i])
j=nxt[j];
if(c[j+1]==c[i])
nxt[i]=++j,Cnt[i]=Cnt[j]+1;
else
Cnt[i]=1,nxt[i]=0;
}
for(int j=0,i=2;i<=len;i++)
{
while(j&&c[j+1]!=c[i]) j=nxt[j];
if(c[j+1]==c[i]) ++j;
while(j<<1>i) j=nxt[j];
(ans*=1ll+Cnt[j])%=mod;
}
printf("%lld\n",ans);
}
return 0;
}
2018.9.6
洛谷 P2375 [NOI2014]动物园 解题报告的更多相关文章
- 【题解】洛谷P2375 [NOI2014] 动物园(KMP)
洛谷P2375:https://www.luogu.org/problemnew/show/P2375 思路 这道题可以说是完全刷新了本蒟蒻对KMP的理解 感觉对next数组的理解上升到一个新的高度 ...
- [洛谷P2375] [NOI2014]动物园
洛谷题目链接:[NOI2014]动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决 ...
- 【KMP】洛谷P2375 [NOI2014]动物园 题解
一开始的方向应该对了,但是没有想到合理的优化还是没写出来…… 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己 ...
- 洛谷 P2375 [NOI2014]动物园
题目传送门 解题思路: 其实对于一个sum[i],其值就等于sum[next[i]] + sum[next[next[i]]] + ... + 1,然后我们可以记忆化,然后题目里又有一个限制,就是前后 ...
- 洛谷 P1783 海滩防御 解题报告
P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...
- 洛谷 P4597 序列sequence 解题报告
P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...
- 洛谷1087 FBI树 解题报告
洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...
- 洛谷 P3349 [ZJOI2016]小星星 解题报告
P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...
- [BZOJ3670] [NOI2014] 动物园 解题报告 (KMP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3670 Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅, ...
随机推荐
- HTML+CSS : 笔记整理(1)
meta:页面描述信息(可以在里面加入作者信息等,如: <meta name="description"content="HTML examples"&g ...
- PHP使用redis(一)
1,connect 描述:实例连接到一个Redis.参数:host: string,port: int返回值:BOOL 成功返回:TRUE;失败返回:FALSE <?php $redis = ...
- POJ 3977 折半枚举
链接: http://poj.org/problem?id=3977 题意: 给你n个数,n最大35,让你从中选几个数,不能选0个,使它们和的绝对值最小,如果有一样的,取个数最小的 思路: 子集个数共 ...
- Codeforces Round #482 (Div. 2) :C - Kuro and Walking Route
题目连接:http://codeforces.com/contest/979/problem/C 解题心得: 题意就是给你n个点,在点集中间有n-1条边(无重边),在行走的时候不能从x点走到y点,问你 ...
- POJ:2385-Apple Catching(dp经典题)
Apple Catching Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14311 Accepted: 7000 Descr ...
- python 函数function
函数 当代码出现有规律的重复的时候,只写一次函数实现多次使用(调用) 可使用的函数: 自定义函数 内置函数:文档 https://docs.python.org/3/library/function ...
- mac上MySQLdb问题解决
早上有个同学问题python访问mysql的问题,之前的写得脚步突然不能运行了,找了很多文章总算解决问题了O(∩_∩)O哈哈~,希望下次不要浪费这么多时间搞这么坑的问题了. mac上MySQLdb ...
- css媒体类型
all 用于所有的媒体设备. aural 用于语音和音频合成器. braille 用于盲人用点字法触觉回馈设备. embossed 用于分页的盲人用点字法打印机. handheld 用于小的手持的设备 ...
- Java语言基础---变量与数据类型
变量的作用域 java用一对大括号“{}”作为语句块的范围,称为作用域.作用域中的变量不能重复定义:离开作用域,变量所分配的内存空间将被JVM所收回. 基本数据类型的包装类 java为基础数据类型提供 ...
- android gridview 停止滚动
http://blog.csdn.net/yaphetzhao/article/details/50544105 参考上面的博客,关键代码我就贴出来吧: public void stopGridVie ...