洛谷 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 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅, ...
随机推荐
- Python学习之购物车
实现功能: 程序启动,提示用户输入用户名和密码,程序读取余额文件last_salary.txt内容(文件不存在则自动创建),若文件内容为空则提示“首次登录,请输入工资”: 用户可以输入商品编号进行购买 ...
- ajax原生js及readystate/status
菜鸟教程 ←← GET: <script> function ajaxGet(){ var xmlhttp; if(window.XMLHttpRequest){ //TE7+ Fi ...
- SQL_server_2008_r2和visual studio 2010旗舰版的安装(2013-01-16-bd 写的日志迁移
(以下操作是在Oracle VM virtualBox虚拟机中操作的,其实VMware Workstation 9虚拟机也挺不错的,不过用了很久的vmware想换个虚拟机用用 就暂时用Oracle V ...
- Small Talk Matters【闲谈很重要】
Small Talk Matters We' ve all been there: in a lift, in line at the bank or on an airplane, 我们都有过这样的 ...
- 关于Java对象作为参数传递是传值还是传引用的问题
前言 在Java中,当对象作为参数传递时,究竟传递的是对象的值,还是对象的引用,这是一个饱受争议的话题.若传的是值,那么函数接收的只是实参的一个副本,函数对形参的操作并不会对实参产生影响:若传的是引用 ...
- 动态调试smali代码
Android Killer对应用进行反编译为smali代码,看看Manifest文件中application标签里面是否有android:debuggable="true",没有 ...
- Android 自定义WebView 实现可以加载缓存数据
1.自定义WebView说明 1.1.这个WebView可以加载缓存的数据.(需要后端配合,将html转换成一个字符串,主要是图片要用特殊格式) 1.2.注入了图片链接,为了方便点击webView中的 ...
- 深入理解Angular2变化监测和ngZone
转载自GitHub JTangming : https://github.com/JTangming/tm/issues/4 Angular应用程序通过组件实例和模板之间进行数据交互,也就是将组件的数 ...
- Docker构建nginx+uwsgi+flask镜像(一)
前言 笔者之前是从事Java方面的工作,自从18年5月左右来到新的公司,接触到Python,被其简单优雅的语法风格深深吸引,同时,新公司也帮助笔者打开Docker世界的大门,让笔者体会到“一次打包,到 ...
- centos 6.X 关闭selinux
SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统.在这种访问控制体系的限制下,进程只能访问那 ...