又被机房神犇肉丝哥哥和glory踩爆了

首先这个答案的输出方式有点套路,当前的答案=上一个答案+每一个后缀的f值=上一个答案+上一次算的每个后缀的f值+当前每个后缀的深度

这个题意给了个根深度为-1有点诡异,考虑它的现实意义是这个后缀在前面出现了几次,这些后缀的深度和就是前面有多少子串和后缀是能匹配的

考虑用SAM把fail树搞出来,那么对于加入一个后缀,就是这个叶子到根的路径的点+1,询问也是问当前点到根的和

拿个LCT维护一下跑路

离线树剖好像更好写 肉丝早就跑路了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int _=1e2;
const int maxn=1e5+_;
const LL mod=1e9+; struct node
{
int f,son[];
LL s,c;//子树内子串总出现数 子树内子串数
LL tot,num;//管理子串数,节点出现次数
LL lazy;
}tr[*maxn];
void update(int now)
{
int lc=tr[now].son[],rc=tr[now].son[];
tr[now].c=tr[lc].c+tr[rc].c+tr[now].tot;
tr[now].s=(tr[lc].s+tr[rc].s+tr[now].tot*tr[now].num+(tr[now].c-tr[now].tot)*tr[now].lazy)%mod;
}
void pushdown(int now)
{
int lc=tr[now].son[],rc=tr[now].son[];
if(lc!=)tr[lc].num+=tr[now].lazy,tr[lc].lazy+=tr[now].lazy,update(lc);
if(rc!=)tr[rc].num+=tr[now].lazy,tr[rc].lazy+=tr[now].lazy,update(rc);
tr[now].lazy=;
}
void rotate(int x,int w)
{
int f=tr[x].f,ff=tr[f].f;
int R,r; R=f,r=tr[x].son[w];
tr[R].son[-w]=r;
if(r!=)tr[r].f=R; R=ff,r=x;
if(tr[ff].son[]==f)tr[R].son[]=r;
else if(tr[ff].son[]==f)tr[R].son[]=r;
tr[r].f=R; R=x,r=f;
tr[R].son[w]=r;
tr[r].f=R; update(f);
update(x);
}
bool isroot(int x,int rt)
{
int f=tr[x].f;
if(f==rt|| tr[f].son[]!=x&&tr[f].son[]!=x )return true;
else return false;
}
int tt,tmp[*maxn];
void splay(int x,int rt)
{
int i=x; tt=;
while(!isroot(i,rt))
tmp[++tt]=i,i=tr[i].f;
tmp[++tt]=i;
while(tt>)
{
if(tr[tmp[tt]].lazy!=)pushdown(tmp[tt]);
tt--;
} while(!isroot(x,rt))
{
int f=tr[x].f,ff=tr[f].f;
if(isroot(f,rt))
{
if(tr[f].son[]==x)rotate(x,);
else rotate(x,);
}
else
{
if(tr[ff].son[]==f&&tr[f].son[]==x)rotate(f,),rotate(x,);
else if(tr[ff].son[]==f&&tr[f].son[]==x)rotate(f,),rotate(x,);
else if(tr[ff].son[]==f&&tr[f].son[]==x)rotate(x,),rotate(x,);
else if(tr[ff].son[]==f&&tr[f].son[]==x)rotate(x,),rotate(x,);
}
}
}
void access(int x)
{
int y=;
while(x!=)
{
splay(x,);
tr[x].son[]=y;
if(y!=)tr[y].f=x;
update(x);
y=x;x=tr[y].f;
}
}
void gotop(int x){access(x),splay(x,);}
void Link(int x,int y){gotop(x),tr[x].f=y;}
void Cut(int x)
{
gotop(x);
int lc=tr[x].son[];
tr[lc].f=;tr[x].son[]=;
update(x);
}
void add(int x)
{
gotop(x);
tr[x].num++;tr[x].lazy++;
update(x);
}
LL getsum(int x){gotop(x);return tr[x].s;}
void change(int x,LL tot)
{
gotop(x);
tr[x].tot=tot;
update(x);
} struct SAM
{
int w[],dep,fail;
}ch[*maxn];int cnt,last;
int gettot(int x){return ch[x].dep-ch[ch[x].fail].dep;}
LL insert(int k,int x)
{
int now=++cnt,pre=last; LL ret=;
ch[now].dep=k;
while(pre!=&&ch[pre].w[x]==)ch[pre].w[x]=now,pre=ch[pre].fail;
if(pre==)
{
ch[now].fail=;
change(now,gettot(now));
Link(now,ch[now].fail);
add(now);
}
else
{
int nxt=ch[pre].w[x];
if(ch[nxt].dep==ch[pre].dep+)
{
ch[now].fail=nxt;
change(now,gettot(now));
Link(now,ch[now].fail);
ret=getsum(now);
add(now);
}
else
{
int nnxt=++cnt; ch[nnxt]=ch[nxt];
ch[nnxt].dep=ch[pre].dep+;
ch[nxt].fail=nnxt; change(nxt,gettot(nxt));
tr[nnxt].num=tr[nxt].num;change(nnxt,gettot(nnxt));
Cut(nxt);
Link(nnxt,ch[nnxt].fail);
Link(nxt,ch[nxt].fail); //.......先处理nnxt和nxt....... ch[now].fail=nnxt;
change(now,gettot(now));
Link(now,ch[now].fail);
ret=getsum(now);
add(now); //........再搞nnxt和now....... while(pre!=&&ch[pre].w[x]==nxt)ch[pre].w[x]=nnxt,pre=ch[pre].fail;
}
}
last=now;
return ret;
} char ss[maxn];
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int n;
scanf("%d%s",&n,ss+); LL ans=,sum=;
cnt=last=;
for(int i=;i<=n;i++)
{
sum=(sum+insert(i,ss[i]-'a'+))%mod;
ans=(ans+sum)%mod;
printf("%lld\n",ans);
} return ;
}

51nod 1600 Simple KMP的更多相关文章

  1. 51Nod 1600 Simple KMP 解题报告

    51Nod 1600 Simple KMP 对于一个字符串\(|S|\),我们定义\(fail[i]\),表示最大的\(x\)使得\(S[1..x]=S[i-x+1..i]\),满足\((x<i ...

  2. 51Nod 1600 Simple KMP SAM+LCT/树链剖分

    1600 Simple KMP 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i)显然对于一个字符串,如果我们将每个0<= ...

  3. 51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*

    Description 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i&l ...

  4. 【51nod1006】simple KMP

    原题意看的挺迷糊的,后来看了http://blog.csdn.net/YxuanwKeith/article/details/52351335大爷的题意感觉清楚的多…… 做法也非常显然了,用树剖维护后 ...

  5. 51nod1600 Simple KMP

    题目描述 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i<=|S|看 ...

  6. HDU 6153 A Secret ( KMP&&DP || 拓展KMP )

    题意 : 给出两个字符串,现在需要求一个和sum,考虑第二个字符串的所有后缀,每个后缀对于这个sum的贡献是这个后缀在第一个字符串出现的次数*后缀的长度,最后输出的答案应当是 sum % 1e9+7 ...

  7. 51Nod 1277 字符串中的最大值(KMP,裸题)

    1277 字符串中的最大值 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 一个字符串的前缀是指包含该字符第一个字母的连续子串,例如: ...

  8. CSU 2056 a simple game (正反进行KMP)超级好题!!!

    Description 这一天,小A和小B在玩一个游戏,他俩每人都有一个整数,然后两人轮流对他们的整数进行操作,每次在下列两个操作任选一个: (1)对整数进行翻转,如1234翻转成4321 ,1200 ...

  9. 51nod 1277字符串中的最大值(拓展kmp)

    题意: 一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd. 给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值.   题解 ...

随机推荐

  1. bzoj[HNOI2015]亚瑟王 - 递推与动规 - 概率与期望

    [bzoj4008][HNOI2015]亚瑟王 2015年4月22日3,2991 Description 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之 ...

  2. Java:Session详解

    以下情况,Session结束生命周期,Servlet容器将Session所占资源释放:1.客户端关闭浏览器2.Session过期3.服务器端调用了HttpSession的invalidate()方法. ...

  3. Admin组件-----Django自带

    1 list_display from django.contrib import admin # Register your models here. from app01.models impor ...

  4. KVM 存储虚拟化

    KVM 的存储虚拟化是通过存储池(Storage Pool)和卷(Volume)来管理的. Storage Pool 是宿主机上可以看到的一片存储空间,可以是多种类型,后面会详细讨论.Volume 是 ...

  5. 标准C程序设计七---27

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  6. Mybatis resultMap空值映射问题

    参考博客:https://www.oschina.net/question/1032714_224673 http://stackoverflow.com/questions/22852383/how ...

  7. P1540 机器翻译(STL 链表)

    题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...

  8. Java中常量定义在interface和class的区别(转)

    最终结论:定义常量在interface和class中其实都行,关键是看你的设计和个人爱好. Java中interface中定义变量默认都是"public static final" ...

  9. 解决Linux系统没有/etc/sysconfig/iptables文件

    Linux系统中,防火墙默认是不开启的,一般也没有配置过任何防火墙的策略,所以不存在/etc/sysconfig/iptables文件. 一.常规解决方法: 1.在控制台使用iptables命令随便写 ...

  10. postgresql 导出建表语句的方法-类似describe table

    https://www.youtube.com/watch?v=PMfcsYzj-9M  这个视频不错, The Definitive Guide to Object-Oriented JavaScr ...