【51nod1006】simple KMP
原题意看的挺迷糊的,后来看了http://blog.csdn.net/YxuanwKeith/article/details/52351335大爷的题意感觉清楚的多……
做法也非常显然了,用树剖维护后缀自动机的parent树。
修改操作看成对每一个状态的right集合全都访问次数+1
询问同理。
然后我忘了更新爬后缀树时候的新状态调了挺久的。。。。。
因为这么傻逼的错误还能过样例。。。。。
#include<bits/stdc++.h>
const int N=2e5+;
const int yql=1e9+;
using namespace std;
int n,rt,tot=,head[N],cnt;
int size[N],wson[N],tpos[N],top[N],fa[N],d[N],len,pre[N];
char s[N];
struct Edge{int u,v,next;}G[N<<];
struct Suffix_AutoMaton{
int ch[N<<][],fa[N<<],l[N<<],cnt,last;
inline void init(){cnt=;last=;}
inline void ins(int c){
int p=last,np=++cnt;last=np;l[np]=l[p]+;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(!p)fa[np]=;
else{
int q=ch[p][c];
if(l[p]+==l[q])fa[np]=q;
else{
int nq=++cnt;l[nq]=l[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
}
}sam;
inline void addedge(int u,int v){
G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
G[++tot].u=v;G[tot].v=u;G[tot].next=head[v];head[v]=tot;
}
inline void dfs1(int u,int f){
size[u]=;
for(int i=head[u];i;i=G[i].next){
int v=G[i].v;if(v==f)continue;
fa[v]=u;d[v]=d[u]+;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[wson[u]])wson[u]=v;
}
}
inline void dfs2(int u,int tp){
tpos[u]=++cnt;pre[cnt]=u;top[u]=tp;
if(wson[u])dfs2(wson[u],tp);
for(int i=head[u];i;i=G[i].next){
int v=G[i].v;
if(v==fa[u]||v==wson[u])continue;
dfs2(v,v);
}
}
struct Segment_Tree{
#define lson (o<<1)
#define rson (o<<1|1)
int sumv[N<<],size[N<<],addv[N<<];
inline void pushup(int o){sumv[o]=(sumv[lson]+sumv[rson])%yql;}
inline void pushdown(int o,int l,int r){
if(!addv[o])return;
addv[lson]+=addv[o];addv[rson]+=addv[o];
sumv[lson]=(sumv[lson]+1LL*size[lson]*addv[o]%yql)%yql;
sumv[rson]=(sumv[rson]+1LL*size[rson]*addv[o]%yql)%yql;
addv[o]=;
}
inline void build(int o,int l,int r){
if(l==r){size[o]=sam.l[pre[l]]-sam.l[sam.fa[pre[l]]];return;}
int mid=(l+r)>>;
build(lson,l,mid);build(rson,mid+,r);
size[o]=(size[lson]+size[rson])%yql;
}
inline int querysum(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sumv[o];
int mid=(l+r)>>,ans=;
pushdown(o,l,r);
if(ql<=mid)ans=(ans+querysum(lson,l,mid,ql,qr))%yql;
if(qr>mid)ans=(ans+querysum(rson,mid+,r,ql,qr))%yql;
return ans;
}
inline void optadd(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){addv[o]+=;if(addv[o]>yql)addv[o]-=yql;sumv[o]=(sumv[o]+size[o])%yql;return;}
int mid=(l+r)>>;pushdown(o,l,r);
if(ql<=mid)optadd(lson,l,mid,ql,qr);
if(qr>mid)optadd(rson,mid+,r,ql,qr);
pushup(o);
}
}T;
int main(){
scanf("%d",&n);
scanf("%s",s+);sam.init();
for(int i=;i<=n;i++)sam.ins(s[i]-'a');
for(int i=;i<=sam.cnt;i++)addedge(sam.fa[i],i);
dfs1(,);dfs2(,);T.build(,,sam.cnt);
int p=,ans=,cur=;
for(int i=;i<=n;i++){
int c=s[i]-'a';int u=sam.ch[p][c];
for(int j=u;j;j=fa[top[j]])cur=(cur+T.querysum(,,sam.cnt,tpos[top[j]],tpos[j]))%yql;
ans=(ans+cur)%yql;printf("%d\n",ans);
for(int j=u;j;j=fa[top[j]])T.optadd(,,sam.cnt,tpos[top[j]],tpos[j]);
p=u;
}
}
【51nod1006】simple KMP的更多相关文章
- P5410 【模板】扩展 KMP
P5410 [模板]扩展 KMP #include<bits/stdc++.h> using namespace std; ; int q, nxt[maxn], extend[maxn] ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- uoj #5. 【NOI2014】动物园 kmp
#5. [NOI2014]动物园 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/5 Description 近日 ...
- 【计数】Simple Addition Expression
[来源] 2008年哈尔滨区域赛 [题目链接]: http://acm.hdu.edu.cn/showproblem.php?pid=2451 [参考博客]: HDU 2451 Simple Addi ...
- 【POJ】【2601】Simple calculations
推公式/二分法 好题! 题解:http://blog.csdn.net/zck921031/article/details/7690288 这题明显是一个方程组……可以推公式推出来…… 然而这太繁琐了 ...
- 【数据结构】 字符串&KMP子串匹配算法
字符串 作为人机交互的途径,程序或多或少地肯定要需要处理文字信息.如何在计算机中抽象人类语言的信息就成为一个问题.字符串便是这个问题的答案.虽然从形式上来说,字符串可以算是线性表的一种,其数据储存区存 ...
- 【XSY2472】string KMP 期望DP
题目大意 给定一个由且仅由字符'H','T'构成的字符串\(S\). 给定一个最初为空的字符串\(T\) ,每次随机地在\(T\)的末尾添加'H'或者'T'. 问当\(S\)为\(T\)的后缀时, ...
- 【BZOJ3670】【NOI2014】动物园 [KMP][倍增]
动物园 Time Limit: 10 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物 ...
- 【BZOJ3942】Censoring [KMP]
Censoring Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 有一个S串和一个T串,长 ...
随机推荐
- 后缀树的线性在线构建-Ukkonen算法
Ukkonen算法是一个非常直观的算法,其思想精妙之处在于不断加字符的过程中,用字符串上的一段区间来表示一条边,并且自动扩展,在需要的时候把边分裂.使用这个算法的好处在于它非常好写,代码很短,并且它是 ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- C++解析(14):静态成员变量与静态成员函数
0.目录 1.静态成员变量 2.静态成员函数 3.小结 1.静态成员变量 成员变量的回顾: 通过对象名能够访问public成员变量 每个对象的成员变量都是专属的 成员变量不能在对象之间共享 新的需求: ...
- DelayQueue实现Java延时任务
最近公司需要实现一个订单超时自动关闭的功能,由Java这块来实现 一开始我以为就是定时任务,深入了解了之后发现并不是,官方名称应该叫延时任务,到时间之后 执行传过来的回调函数 这个功能我一共前前后后写 ...
- 【JavaScript】Json
一.前言 接着上一章的内容,继续js的学习. 二.内容 解析与序列化 JSON.stringify() —— 将js对象序列化为JSON字符串,接收三个参数:1.js对象2 ...
- Python精要参考(第二版)
ython 精要参考(第二版) 是Python语言初学者不错的参考学习用书,本系列译自Python Essential Reference, Second Edition 希望本系列可以给python ...
- 【学习笔记】ac自动机&fail树
定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...
- [HEOI2015]公约数数列
不错的分块题 gcd和xor其实并没有联系 这里,xor的按位性质没有半点卵用 gcd的性质却很关键: 一个数组,前缀gcd最多logn个不同的 gcd不太多,(暴力的基础) 所有考虑分块. 分块,每 ...
- 【bzoj4571】美味
Portal -->bzoj4571 Solution emmm持续智力康复.. 虽然说因为统计的是加上\(x\)的跟\(b\)异或的最大值所以可持久化trie用不了了 但是按位贪心的思想还 ...
- Ubuntu下Sublime Text 2优化配置
以前经常用Notepad++,最近因为需要长期在Linux环境下进行C开发,就使用了sublime Text 2,这里就不介绍基本的了主要针对我使用的经验中进行一些总结. 1.pacage contr ...