一道神仙题,考察选手对KMP的深入理解。

先考虑没有2操作的做法。设每一段为一个二元组(x,c),考虑一段前缀匹配后缀,除了第一段的字符,其他段的二元组(x,c)必须相等,所以可以将其视为特殊字符进行匹配。在串末尾加入(x,c)时,显然不断跳next数组,如果当前前缀后接的字符为c ,那么可以增加一段首项为当前前缀长度,然后发现这一段的next数组为首项为前缀长度,公差为1的等差数列。next链上如果有等于(x,c)的二元组,则next指向二元组,否则指向0,因为如果存在(y,c)满足y>x,则一定无法匹配。

解决了没有2操作的做法,考虑有2操作,由于KMP复杂度是均摊的,很显然不能直接在树上dfs,所以要优化求next过程。考虑离线建树,dfs时维护每条next链上的KMP自动机,f[i][j][k]表示状态i下加入二元组(j,k)next指向哪,g[i][j][k]表示产生的贡献,每次修改复制前一次的f数组,修改f[i][x][c],g[i][x][1...c]为等差数列,此处可以用主席树实现。

#include<bits/stdc++.h>
#define lson l,mid,tr[rt].lc
#define rson mid+1,r,tr[rt].rc
using namespace std;
const int N=1e5+,M=1e4+,mod=;
struct node{int lc,rc,sum,lazy,nxt;}tr[N*];
int n,tot,top,val[N],pos[N],ans[N],a[N],b[N],rt[N][],mx[N][];
vector<int>G[N];
void newnode(int&x){tr[++tot]=tr[x],x=tot;}
void add(int x,int v,int len){tr[x].sum=1ll*v*len%mod,tr[x].lazy=v;}
int S(int x){return 1ll*x*(x+)/%mod;}
void pushdown(int l,int r,int rt)
{
if(!tr[rt].lazy)return;
int mid=l+r>>;
newnode(tr[rt].lc),add(tr[rt].lc,tr[rt].lazy,mid-l+);
newnode(tr[rt].rc),add(tr[rt].rc,tr[rt].lazy,r-mid);
tr[rt].lazy=;
}
void update(int k,int v,int p,int l,int r,int&rt)
{
newnode(rt);
if(r<k){add(rt,v,r-l+);return;}
if(l==r){tr[rt].nxt=p,add(rt,v,);return;}
pushdown(l,r,rt);
int mid=l+r>>;
update(k,v,p,lson);
if(k>mid)update(k,v,p,rson);
tr[rt].sum=(tr[tr[rt].lc].sum+tr[tr[rt].rc].sum)%mod;
}
void query(int k,int&ans,int&nxt,int l,int r,int&rt)
{
if(r<k){ans=(ans+tr[rt].sum)%mod;return;}
if(l==r){ans=(ans+tr[rt].sum)%mod,nxt=tr[rt].nxt;return;}
pushdown(l,r,rt);
int mid=l+r>>;
query(k,ans,nxt,lson);
if(k>mid)query(k,ans,nxt,rson);
}
void dfs(int u)
{
++top;
int x=val[u]/M,y=val[u]%M,nxt=;
a[top]=val[u],b[top]=b[top-]+y;
if(top==)ans[u]=S(y-);
else{
ans[u]=(ans[u]+S(min(mx[top][x],y)))%mod;
query(y,ans[u],nxt,,M,rt[top][x]);
if(!nxt&&a[]/M==x&&b[]<y)nxt=,ans[u]=(ans[u]+1ll*b[]*max(,y-mx[top][x]))%mod;
}
mx[top][x]=max(mx[top][x],y);
update(y,b[top-],top,,M,rt[top][x]);
for(int i=;i<G[u].size();i++)
{
memcpy(mx[top+],mx[nxt+],sizeof mx[top+]);
memcpy(rt[top+],rt[nxt+],sizeof rt[top+]);
ans[G[u][i]]=ans[u],dfs(G[u][i]);
}
--top;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==)
{
char c;cin>>c;
val[++tot]=(c-'a')*M+x,pos[i]=tot,G[pos[i-]].push_back(pos[i]);
}
else pos[i]=pos[x];
}
for(int i=;i<G[].size();i++)
{
tot=;
memset(rt[],,sizeof rt[]);
memset(mx[],,sizeof mx[]);
dfs(G[][i]);
}
for(int i=;i<=n;i++)printf("%d\n",ans[pos[i]]);
}

[HNOI2019]JOJO(KMP自动机+主席树)的更多相关文章

  1. LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树

    题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...

  2. NOI 2011 阿狸的打字机(AC自动机+主席树)

    题意 https://loj.ac/problem/2444 思路 ​多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...

  3. Bzoj2534:后缀自动机 主席树启发式合并

    国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...

  4. luogu P5826 【模板】子序列自动机 主席树 vector 二分

    LINK:子序列自动机 想了一些很有趣的做法. dp 容易看出 f[i][j]表示前i个数匹配了j个数的dp 不过复杂度很高. 贪心 容易想到匹配的时候每个数字尽量往前匹配 这样显然是最优的 复杂度Q ...

  5. CodeForces 547E Mike and Friends AC自动机 主席树

    题意: 给出\(n\)个字符串\(s_i\)和\(q\)个询问: \(l,r,k\):\(\sum\limits_{i=l}^{r}count(i, k)\),其中\(count(i,j)\)表示\( ...

  6. 【洛谷5287】[HNOI2019] JOJO(主席树优化KMP)

    点此看题面 大致题意: 每次往一个字符串末尾加上\(x\)个字符\(c\),或者回到某一历史版本,求\(KMP\)的\(\sum Next_i\). 问题转化 考虑到可以离线. 于是,我们就可以用一个 ...

  7. 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 657  Solved: 274[Su ...

  8. CodeForces 547E:Mike and Friends(AC自动机+DFS序+主席树)

    What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...

  9. CF547E Milk and Friends(AC自动机的fail指针上建主席树 或 广义后缀自动机的parent线段树合并)

    What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...

随机推荐

  1. NET CLR via C#(第4版)第4章 类型基础

    本章内容: 1 所有类型都从System.Object派生 2 类型转换 3 命名空间和程序集 4 运行时的相互关系   本章讲述使用类型和CLR时需掌握的基础知识.具体地说,要讨论所有类型都具有的一 ...

  2. zookeeper基础教程

    一.关于zookeeper Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储, Zookeeper 作用 ...

  3. DRF项目之JWT认证方式的简介及使用

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...

  4. python3.4+Django+pymysql

    pip install Pymysql 修改app里面的__init__.py import pymysqlpymysql.install_as_MySQLdb()

  5. Cracking Digital VLSI Verification Interview 第一章

    目录 Digital Logic Design Number Systems, Arithmetic and Codes Basic Gates Combinational Logic Circuit ...

  6. Python pip安装时You are using pip version 9.0.1, however version 18.0 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command.

    在我们安装第三方库的时候会在结尾出现如下两行内容 You are using pip version 9.0.1, however version 18.0 is available. You sho ...

  7. C# 创建Windows服务。服务功能:定时操作数据库

      一.创建window服务 1.新建项目-->选择Windows服务.默认生成文件包括Program.cs,Service1.cs 2.在Service1.cs添加如下代码: System.T ...

  8. win10使用笔记本自带显卡GUP安装CUDA,版本问题

    1.GPU算力问题 查询:win+r, GPU:GeForce GTX 850m,算力5.0,还可以跑得起来深度项目 2.我们需要查看NVIDIA驱动版本,才能安装合适的CUDA版本. 在C:\Pro ...

  9. java RSA 加密解密

    package com.rsa; import java.security.KeyFactory; import java.security.KeyPair; import java.security ...

  10. 机器学习分布式框架horovod安装 (Linux环境)

    1.openmi 下载安装 下载连接: https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.1.tar.gz 安装命令 1 ...