原题意看的挺迷糊的,后来看了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的更多相关文章

  1. P5410 【模板】扩展 KMP

    P5410 [模板]扩展 KMP #include<bits/stdc++.h> using namespace std; ; int q, nxt[maxn], extend[maxn] ...

  2. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  3. uoj #5. 【NOI2014】动物园 kmp

    #5. [NOI2014]动物园 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/5 Description 近日 ...

  4. 【计数】Simple Addition Expression

    [来源] 2008年哈尔滨区域赛 [题目链接]: http://acm.hdu.edu.cn/showproblem.php?pid=2451 [参考博客]: HDU 2451 Simple Addi ...

  5. 【POJ】【2601】Simple calculations

    推公式/二分法 好题! 题解:http://blog.csdn.net/zck921031/article/details/7690288 这题明显是一个方程组……可以推公式推出来…… 然而这太繁琐了 ...

  6. 【数据结构】 字符串&KMP子串匹配算法

    字符串 作为人机交互的途径,程序或多或少地肯定要需要处理文字信息.如何在计算机中抽象人类语言的信息就成为一个问题.字符串便是这个问题的答案.虽然从形式上来说,字符串可以算是线性表的一种,其数据储存区存 ...

  7. 【XSY2472】string KMP 期望DP

    题目大意 给定一个由且仅由字符'H','T'构成的字符串\(S\). ​ 给定一个最初为空的字符串\(T\) ,每次随机地在\(T\)的末尾添加'H'或者'T'. 问当\(S\)为\(T\)的后缀时, ...

  8. 【BZOJ3670】【NOI2014】动物园 [KMP][倍增]

    动物园 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物 ...

  9. 【BZOJ3942】Censoring [KMP]

    Censoring Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 有一个S串和一个T串,长 ...

随机推荐

  1. hadoop跑第一个实例过程

    第一次跑hadoop实例,中间经过了不少弯路,特此记录下来: 第一步:建立一个maven过程,pom.xml文件:(打包为jar包) <dependency> <groupId> ...

  2. bzoj1272 Gate Of Babylon(计数方法+Lucas定理+乘法逆元)

    Description Input Output Sample Input 2 1 10 13 3 Sample Output 12 Source 看到t很小,想到用容斥原理,推一下发现n种数中选m个 ...

  3. 解析php addslashes()与addclashes()函数的区别和比较

    一. addslashes() 函数 addslashes(string) 函数在指定的预定义字符前添加反斜杠.这些预定义字符是:•单引号 (')•双引号 (")•反斜杠 (\)•NULL  ...

  4. C++解析(25):关于动态内存分配、虚函数和继承中强制类型转换的疑问

    0.目录 1.动态内存分配 1.1 new和malloc的区别 1.2 delete和free的区别 2.虚函数 2.1 构造函数与析构函数是否可以成为虚函数? 2.2 构造函数与析构函数是否可以发生 ...

  5. Opencv2.4.9+win7+VS2012一次性配置的方法--通过建立属性表永久配置

    Opencv的配置对于初学者很麻烦,网上的教程也非常多,针对不同的操作系统.opencv版本.Visual studio版本都有相应的教程,但即便是按照教程一步一步来,仍然难免出错,很多教程还是一次性 ...

  6. 【BZOJ3672】【NOI2014】购票(线段树,斜率优化,动态规划)

    [BZOJ3672][NOI2014]购票(线段树,斜率优化,动态规划) 题解 首先考虑\(dp\)的方程,设\(f[i]\)表示\(i\)的最优值 很明显的转移\(f[i]=min(f[j]+(de ...

  7. bzoj4873 [Shoi2017]寿司餐厅

    Input 第一行包含两个正整数n,m,分别表示这家餐厅提供的寿司总数和计算寿司价格中使用的常数. 第二行包含n个正整数,其中第k个数ak表示第k份寿司的代号. 接下来n行,第i行包含n-i+1个整数 ...

  8. git 还原某个文件到特定版本

    1.先使用 git log 查看需要还原的版本号 2.git checkout <版本号> <文件相对路径> 3.git commit -m "xxx"

  9. python学习笔记(五) 200行实现2048小游戏

    用前文提到的基础知识,和网上流行的2048源码,用python实现该游戏. 先将用户操作和游戏逻辑绑定. WASD分别对应移动方向上.左.下.右 然后实现矩阵的转置和逆置,这样只要实现一个方向的移动, ...

  10. poppo大根堆的原理与实现。

    大根堆的定义:1 大根堆是一个大根树 2 大根堆是一个完全二叉树 所以大根堆用数组表示是连续的,不会出现空白字段. 对于大根堆的插入 对于大根堆的插入,可以在排序前确定大根堆的形状,可以确定元素5从位 ...