BZOJ 4175: 小G的电话本 SAM+FFT
4175: 小G的电话本
Time Limit: 45 Sec Memory Limit: 256 MB
Submit: 195 Solved: 48
[Submit][Status][Discuss]
Description
小G是一个商人,他有一个电话本。电话本上记下了许多联系人,如timesqr、orzyhb等等。不过Tony对其中的某个联系人的名字S特别感兴趣,他从中提取出了这个联系人的名字中的所有片段,如提取出orz的 o、r、z、or、rz、orz等等。现在他想请你统计有多少个长度为k的片段对(P[1], P[2], P[3], ..., P[k]),使得在该片段对中所有片段在S中出现次数之和为他的幸运数m?注意两个片段对不同当且仅当两个片段对的某一位的片段不同,两个片段不同当且仅当这两个片段在S中的位置不同
Input
第一行两个整数k和m,意义见题目描述;第二行给出一个字符串表示Tony喜欢的联系人名字S。
Output
输出一行一个整数ans,表示答案模1005060097。
Sample Input
aaaaa
Sample Output
HINT
【样例解释】
#include<cstdio>
#include<cstring>
#define ll long long
const int len(100000),MP(1005060097),g(5),lem(262144);
struct SamNode{int nx[26],pre,right,step;}sam[len*2+10];
int top=1,root=1,now=1,last,lastson;
int cnt[len+10],p[len*2+10],b[len+10];
int n,m,k;char str[len+10];
void insert(int x)
{
last=now;now=++top;sam[now].step=sam[last].step+1;sam[now].right=1;
for(;!sam[last].nx[x]&&last;last=sam[last].pre)
sam[last].nx[x]=now;
if(!last)sam[now].pre=root;
else
{
lastson=sam[last].nx[x];
if(sam[lastson].step==sam[last].step+1)sam[now].pre=lastson;
else
{
++top;
memcpy(sam[top].nx,sam[lastson].nx,sizeof(sam[top].nx));
sam[top].pre=sam[lastson].pre;
sam[top].step=sam[last].step+1;
sam[lastson].pre=sam[now].pre=top;
for(;sam[last].nx[x]==lastson&&last;last=sam[last].pre)
sam[last].nx[x]=top;
}
}
}
void update()
{
for(int i=1;i<=top;i++)cnt[sam[i].step]++;
for(int i=1;i<=n;i++)cnt[i]+=cnt[i-1];
for(int i=top;i>=1;i--)p[cnt[sam[i].step]--]=i;
for(int i=top;i>=1;i--)
{
sam[sam[p[i]].pre].right+=sam[p[i]].right;
b[sam[p[i]].right]=(b[sam[p[i]].right]+1ll*sam[p[i]].right*(sam[p[i]].step-sam[sam[p[i]].pre].step))%MP;
}
} int R[lem+10],w[lem+10],wn,il,l,h;
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
int power(int a,int b)
{
if(b<0)b=MP-1+b; long long t=1,y=a;
while(b){if(b&1)t=(t*y)%MP;y=(y*y)%MP;b>>=1;}
return (int)t;
}
struct Arr
{
void NTT(int *a,int l,int ty)
{
for(int i=0;i<l;i++)
if(i<R[i])swap(a[i],a[R[i]]);
for(int leng=2;leng<=l;leng<<=1)
{
int M=leng>>1;
wn=power(g,ty*((MP-1)/leng));
for(int i=1;i<M;i++)w[i]=(1ll*w[i-1]*wn)%MP;
for(int i=0;i<l;i+=leng)
{
for(int j=0;j<M;j++)
{
int x=a[i+j],y=(1ll*w[j]*a[i+j+M])%MP;
a[i+j]=x+y;a[i+j+M]=x-y;
a[i+j]-=a[i+j]>=MP?MP:0;
a[i+j+M]+=a[i+j+M]<0?MP:0;
}
}
}
if(ty==-1)
for(int i=0;i<l;i++)a[i]=(1ll*a[i]*il)%MP;
}
int a[lem+10];//只保留前m项
void mul(Arr &C)
{
NTT(a,l,1);
NTT(C.a,l,1);
for(int j=0;j<l;j++)a[j]=(1ll*a[j]*C.a[j])%MP;
NTT(a,l,-1);for(int j=m+1;j<l;j++)a[j]=0;
}
}X,Y,C;
void deal()
{
l=1;while(l<=m+m+1)l<<=1,h++;
for(int i=0;i<l;i++)R[i]=(R[i>>1]>>1|(i&1)<<(h-1));
il=power(l,MP-2);
}
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
scanf("%d%d",&k,&m);
scanf("%s",str);n=strlen(str);
for(int i=0;i<n;i++)insert(str[i]-'a');
update();deal();w[0]=1;
X.a[0]=1;for(int i=0;i<=m;i++)Y.a[i]=b[i];//,printf("%d\n",b[i])
for(;k;k>>=1,C=Y,Y.mul(C))
{
// printf("Y\n");
// for(int i=0;i<=m;i++)printf("%d\n",Y.a[i]);
if(k&1)C=Y,X.mul(C);
// printf("X\n");
// for(int i=0;i<=m;i++)printf("%d\n",Y.a[i]);
}
printf("%d",X.a[m]);
return 0;
}
BZOJ 4175: 小G的电话本 SAM+FFT的更多相关文章
- BZOJ 4175 小G的电话本 ——NTT
后缀自动机统计出现了各种次数的串的和. 就是所谓的生成函数 然后FFT卷积即可. 卷积快速幂$n\log n \log n$ 注意一下实现,可以少两次NTT #include <map> ...
- BZOJ4175 : 小G的电话本
用后缀树统计出出现了x次的本质不同的子串的个数,最后再乘以x,得到一个多项式. 这个多项式常数项为0,但是一次项不为0. 于是把整个多项式除以一次项,通过多项式求ln和多项式求exp求出它的幂. 最后 ...
- [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性)
[BZOJ 1563] [NOI 2009] 诗人小G(决策单调性) 题面 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以放的句子数目是没有限制的.小 G ...
- C语言实现电话本 动态开辟 信息存储于文件
下面是我用C写的一个电话本小项目,实现的功能有:添加 删除 修改 查找 排序 清空 显示,功能还是比较全的,内存也是动态开辟的.能存储于本地,能从本地读出并显示 头文件部分代码,contact.h: ...
- BZOJ 5028 小z的加油站
bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...
- 微信电话本可免费拨打网络电话 通话一分钟约300K流量
微信电话本新版本于昨日晚间发布,这是一款智能通讯增强软件,通话双方都下载此APP并开通免费通话功能就能使用微信电话本拨打免费网络电话,在对方无法接通情况下还能将音频转向语音信箱,微信电话本目前支持An ...
- C++之路进阶——codevs2933(诗人小G)
2933 诗人小G 2009年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 小G是一个出色的诗人 ...
- 苹果IPhone手机由于更新了IOS7 Beta测试版导致“激活出错”后,如何还原电话本和照片方法
苹果这狗日的,手段果然狠,因为用户提前升级了测试版又没有更新正式版,就突然把手机变砖头,既不让升级正式版,也不让备份手机中的信息,确实有必要这样吗? 我的手机是IPone4s,在看了6月Apple W ...
- Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2
分析下怎么写 首先,我们需要一个输入框,可以手动的输入手机号码, 其次,很少有人愿意手动输入,那么我们需要提供一个按钮来给我们的用户选择自己电话本中的联系人(一次可以选择多个即群发) 然后,我们需要一 ...
随机推荐
- 微信小程序开发之日期组件
一: wxml: <view class="navbarlift" style="background:#ffffff;padding:20rpx"> ...
- 利用oracle session context 向oracle传值
有时候,我们在执行数据库请求时,需要向数据库传一些应用程序的上下文信息,比如当前应用的用户.举个场景,我们要通过触发器记录对某些关键表的修改日志,日志包括修改的表,字段,字段的值,修改的时间,当然非常 ...
- iOS三方支付--微信支付/支付宝支付
一.微信支付 1.注册账号并申请app支付功能 公司需要到微信开放品台进行申请app支付功能 , 获得appid和微信支付商户号(mch_id)和API秘钥(key) . Appsecret(secr ...
- IOSerialize,xml和json,soap序列化器,二进制序列化器,XML序列化器,文件 检查、新增、复制、移动、删除
1 文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/读取配置文件3 三种序列化器4 xml和json1.文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/ ...
- UE4 c++ 创建刚体Cube
1 新建一个Actor,一会用蓝图继承这个 TCubeActor.h #pragma once #include "CoreMinimal.h" #include "Ga ...
- UE4]不使用角色蓝图、动画蓝图、状态机,用“24K纯C++”实现动画播放
http://aigo.iteye.com/blog/2283454 原文作者:@玄冬Wong 不好意思,我稍稍标题党了,目前还不清楚如何用C++代码来实现BlendSpace和Montage的逻辑, ...
- 非常实用的Sublime插件集合 – sublime推荐必备插件
插件介绍 ***PackageControl*** 功能:安装包管理 简介:sublime插件控制台,提供添加.删除.禁用.查找插件等功能 使用方法: 1.安装好控制台,如有不能正常调用 Packag ...
- html常用标签及属性,常用英语单词
目录 html常用标签 html常用标签属性 前端常用英语单词表(未完待续) 欢迎评论点赞交流,转发请添加原博客连接谢谢! Ctrl键+F 可以查找你想要的内容哦! html常用标签 htmi结构 & ...
- Swing 100行画图示例
关键内容,可以自行扩展 package main; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt ...
- 10.使用子查询 ---SQL
利用子查询进行过滤 普通查询: SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'; 输出▼ order_num ----------- ...