【51nod1006】simple KMP

原题意看的挺迷糊的,后来看了http://blog.csdn.net/YxuanwKeith/article/details/52351335大爷的题意感觉清楚的多……

做法也非常显然了,用树剖维护后缀自动机的parent树。

修改操作看成对每一个状态的right集合全都访问次数+1

询问同理。

然后我忘了更新爬后缀树时候的新状态调了挺久的。。。。。

因为这么傻逼的错误还能过样例。。。。。

#include<bits/stdc++.h>
const int N=2e5+10;
const int yql=1e9+7;
using namespace std;
int n,rt,tot=0,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<<1];
struct Suffix_AutoMaton{
    int ch[N<<1][26],fa[N<<1],l[N<<1],cnt,last;
    inline void init(){cnt=1;last=1;}
    inline void ins(int c){
        int p=last,np=++cnt;last=np;l[np]=l[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q])fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                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]=1;
    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]+1;
        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<<2],size[N<<2],addv[N<<2];
    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]=0;
    }
    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)>>1;
        build(lson,l,mid);build(rson,mid+1,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)>>1,ans=0;
        pushdown(o,l,r);
        if(ql<=mid)ans=(ans+querysum(lson,l,mid,ql,qr))%yql;
        if(qr>mid)ans=(ans+querysum(rson,mid+1,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]+=1;if(addv[o]>yql)addv[o]-=yql;sumv[o]=(sumv[o]+size[o])%yql;return;}
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(ql<=mid)optadd(lson,l,mid,ql,qr);
        if(qr>mid)optadd(rson,mid+1,r,ql,qr);
        pushup(o);
    }
}T;
int main(){
    scanf("%d",&n);
    scanf("%s",s+1);sam.init();
    for(int i=1;i<=n;i++)sam.ins(s[i]-‘a‘);
    for(int i=1;i<=sam.cnt;i++)addedge(sam.fa[i],i);
    dfs1(1,0);dfs2(1,1);T.build(1,1,sam.cnt);
    int p=1,ans=0,cur=0;
    for(int i=1;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(1,1,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(1,1,sam.cnt,tpos[top[j]],tpos[j]);
        p=u;
    }
}
时间: 2024-10-03 13:46:26

【51nod1006】simple KMP的相关文章

uoj #5. 【NOI2014】动物园 kmp

#5. [NOI2014]动物园 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/5 Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S它的长度为L.我们可以在O(L)的时间内求出一个名为next

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

动物园 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数

【POJ】【2601】Simple calculations

推公式/二分法 好题! 题解:http://blog.csdn.net/zck921031/article/details/7690288 这题明显是一个方程组……可以推公式推出来…… 然而这太繁琐了!发现a[i]是满足单调性的话,我们就可以二分a[1],递推出a[n+1],进行验证…… 思维复杂度比推公式低到不知哪里去了,真是一种优秀的算法(然而我想不到,并没有什么*用……) 1 Source Code 2 Problem: 2601 User: sdfzyhy 3 Memory: 736K

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

字符串 作为人机交互的途径,程序或多或少地肯定要需要处理文字信息.如何在计算机中抽象人类语言的信息就成为一个问题.字符串便是这个问题的答案.虽然从形式上来说,字符串可以算是线性表的一种,其数据储存区存储的元素是一个个来自于选定字符集的字符,但是字符串由于其作为一个整体才有表达意义的这个特点,显示出一些特殊性.人们一般关注线性表都会关注其元素和表的关系以及元素之间的关系和操作,而字符串常常需要一些对表整体的关注和操作. 字符串的基本概念如长度,比大小,子字符串等等这些,只要有点编程基础的人都懂就不

【NOI2014】动物园 - KMP

题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数组的含义吗?” 熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[i].” 园长:“非

【bzoj3670】[Noi2014]动物园

3670: [Noi2014]动物园 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2080  Solved: 1107[Submit][Status][Discuss] Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:"对于一个字符串S,它的长度

暑假N天乐【比赛篇】 —— 2019杭电暑期多校训练营(第五场)

开启疯狂水题解模式,大概会持续好几次...直到我赶上进度为止. 以下题解包括: \[1001[HDU-6624] \\ 1004[HDU-6627] \\ 1005[HDU-6628] \\ 1006[HDU-6629] \\ 1007[HDU-6630]\] [1001] 数学 HDU-6624 fraction http://acm.hdu.edu.cn/showproblem.php?pid=6624 找到最小正整数的 \(b\) 满足 \(a<b\) 且 \(a = bx(mod \ p

【转】从头到尾彻底理解KMP

很好,讲得很清晰,值得学习. 作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个月从早到晚不断改进. 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得非常混乱,如此,留言也是“骂声”一片.所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不够,故才迟迟没有修改本文. 然近期因在北京开了个算法班,专门讲解数据结构.面试.算法,才再次仔细回顾了这个KMP,在综合了一些网友的理解

【洛谷】3375 KMP字符串匹配

[算法]KMP [题解][算法]字符串 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1000010,maxm=1010; char A[maxn],B[maxm]; int p[maxm],n,m; int main() { scanf("%s%s",A+1,B+1); n=strlen(A+1);m=strlen