BZOJ5408: string(广义后缀自动机,LCT)
解题思路:
首先在后缀树上,确定了一个节点就相当于确定了一个串,那么一个点对应的串在另外一个点对应的串产生贡献,当且仅当这个点在当前点子树内。
那么考虑一个新的点在串中对串答案的贡献在一条树链上或者反过来说,就是产生贡献的点在这个点子树内。
才知道自己写的广义后缀自动机板子是错的QAQ
考虑n非常小,贡献可以单独算,再配合BZOJ2555的启发,这道题就可以使用LCT轻松地解决了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
typedef long long lnt;
struct trnt{
int ch[];
int fa;
int val[];
int lzt[];
bool anc;
}tr[];
struct sant{
int tranc[];
int pre;
int len;
}s[];
int n,m;
lnt sum;
int siz;
int type;
int lastans;
int pos[][];
char str[];
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void add(int spc,int no,int v)
{
if(!spc)return ;
tr[spc].val[no]+=v;
tr[spc].lzt[no]+=v;
return ;
}
void pushdown(int spc)
{
for(int i=;i<=n;i++)
{
if(tr[spc].lzt[i])
{
add(lll,i,tr[spc].lzt[i]);
add(rrr,i,tr[spc].lzt[i]);
tr[spc].lzt[i]=;
}
}
}
void recal(int spc)
{
if(!tr[spc].anc)recal(tr[spc].fa);
pushdown(spc);
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
if(tr[f].anc)
{
tr[f].anc=false;
tr[spc].anc=true;
}else tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
return ;
}
void splay(int spc)
{
recal(spc);
while(!tr[spc].anc)
{
int f=tr[spc].fa;
if(tr[f].anc)
{
rotate(spc);
return ;
}
if(whc(spc)^whc(f))rotate(spc);
else rotate(f);
rotate(spc);
}
return ;
}
void access(int spc)
{
int lst=;
while(spc)
{
splay(spc);
tr[rrr].anc=true;
tr[lst].anc=false;
rrr=lst;
lst=spc;
spc=tr[spc].fa;
}
return ;
}
void ADD(int from,int to,int cmd)
{
recal(from);
for(int i=;i<=n;i++)
{
if(tr[from].val[i])
{
add(to,i,tr[from].val[i]*cmd);
}
}
return ;
}
void link(int x,int f)
{
access(f);
splay(f);
splay(x);
ADD(x,f,);
tr[x].fa=f;
return ;
}
void cut(int spc)
{
access(spc);
splay(spc);
int spc_=lll;
lll=tr[spc_].fa=;
tr[spc_].anc=true;
splay(spc_);
ADD(spc,spc_,-);
return ;
}
int decode(int c)
{
if(type)return (c xor lastans)%;
return c;
}
int Insert(int fin,int no,int c)
{
if(s[fin].tranc[c]&&s[s[fin].tranc[c]].len==s[fin].len+)
{
int spc=s[fin].tranc[c];
access(spc);
splay(spc);
add(spc,no,);
return spc;
}
int nwp,lsp,nwq,lsq,flag=;
nwp=++siz;tr[nwp].val[no]=;
s[nwp].len=s[fin].len+;
for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)s[lsp].tranc[c]=nwp;
if(!lsp)
{
s[nwp].pre=;
link(nwp,);
}else{
lsq=s[lsp].tranc[c];
if(s[lsq].len==s[lsp].len+)
{
s[nwp].pre=lsq;
link(nwp,lsq);
}else{
if(s[nwp].len==s[lsp].len+)flag=;
nwq=++siz;
s[nwq]=s[lsq];
s[nwq].len=s[lsp].len+;
s[nwp].pre=s[lsq].pre=nwq;
cut(lsq);
link(nwq,s[nwq].pre);
link(nwp,nwq);
link(lsq,nwq);
while(s[lsp].tranc[c]==lsq)
{
s[lsp].tranc[c]=nwq;
lsp=s[lsp].pre;
}
}
}
sum+=s[nwp].len-s[s[nwp].pre].len;
if(flag)return nwq;
return nwp;
}
void init(void)
{
for(int i=;i<=;i++)tr[i].anc=true;
siz=;
return ;
}
int query(char *a)
{
int len=strlen(a+);
int spc=;
for(int i=;i<=len;i++)
{
int c=a[i]-'';
spc=s[spc].tranc[c];
if(!spc)return ;
}
int ans=-;
recal(spc);
for(int i=;i<=n;i++)
ans=std::max(ans,tr[spc].val[i]);
return ans;
}
int main()
{
scanf("%d%d",&n,&type);
init();
for(int i=;i<=n;i++)
{
scanf("%s",str+);
int len=strlen(str+);
pos[i][]=;
for(int j=;j<=len;j++)
pos[i][]=Insert(pos[i][],i,str[j]-'');
}
scanf("%d",&m);
for(int r=;r<=m;r++)
{
for(int i=;i<=n;i++)pos[i][r]=pos[i][r-];
int opt;
scanf("%d",&opt);
if(opt==)
{
int x,y;
scanf("%d%d",&x,&y);
y=decode(y);
pos[x][r]=Insert(pos[x][r],x,y);
}
if(opt==)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int spc=pos[x][y];
recal(spc);
lastans=tr[spc].val[z];
printf("%d\n",lastans);
}
if(opt==)printf("%lld\n",sum);
if(opt==)
{
scanf("%s",str+);
lastans=query(str);
printf("%d\n",lastans);
}
}
return ;
}
BZOJ5408: string(广义后缀自动机,LCT)的更多相关文章
- 2020牛客暑期多校训练营(第四场) C - Count New String (字符串,广义后缀自动机,序列自动机)
Count New String 题意: 定义字符串函数 \(f(S,x,y)(1\le x\le y\le n)\),返回一个长度为y-x+1的字符串,第 i 位是 \(max_{i=x...x+k ...
- BZOJ 3277 串 (广义后缀自动机)
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
- BZOJ 3473: 字符串 [广义后缀自动机]
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 354 Solved: 160[Submit][Status][Discuss] ...
- cf666E. Forensic Examination(广义后缀自动机 线段树合并)
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...
- SP8093 JZPGYZ - Sevenk Love Oimaster(广义后缀自动机)
题意 题目链接 Sol 广义后缀自动机板子题..和BZOJ串那个题很像 首先建出询问串的SAM,然后统计一下每个节点被多少个串包含 最后直接拿询问串上去跑就行了 #include<bits/st ...
- BZOJ 3473: 字符串 (广义后缀自动机)
/* 广义后缀自动机, 每次加入维护 该right集合的set, 然后可以更新所有的parent,最终能够出现在k个串中right集合也就是set大小大于等于k的部分 这样的话就给了我们要跳的节点加了 ...
- bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...
- 【BZOJ2780】Sevenk Love Oimaster【广义后缀自动机】
题意 给出你n个字符串和q个查询,每个查询给出一个字符串s,对于每个查询你都要输出这个字符串s在上面多少个字符串中出现过. 分析 广义后缀自动机的裸题.建好SAM以后再跑一遍得到每个状态的ocu和la ...
- 【BZOJ3227】串【广义后缀自动机】
题意 给出n个字符串,问每个字符串中有多少子串是这所有的n个字符串中至少k个的子串. 分析 广义后缀自动机模板题.对这n个串建广义后缀自动机,对于每个状态维护两个值cou[u]和lcu[u]分别代表拥 ...
随机推荐
- [MST] Store Store in Local Storage
For an optimal user and developer experience, storing state in local storage is often a must. In thi ...
- 使用IR2101半桥驱动电机的案例
作为一个电机驱动开发方面的菜鸟,近日研究了一下通过MOS管对整流后的电源斩波用以驱动直流电机进行调速的方案. 在驱动的过程中,遇到了很多问题,当然也有很多的收获. 写下来以供自己将来查阅,也为其他菜鸟 ...
- unity3d 自己主动文件更新系统
游戏内容变更之后.一般而言不会想让玩家下载整个游戏包又一次安装,由于这样会流失大量玩家.全部游戏更新是必须的. 更新的内容包含 数据.资源.代码. 基本原理: 1.将须要更新的文件打包成AssetBu ...
- OpenCASCADE点向平面投影
OpenCASCADE点向平面投影 OpenCASCADE的ProjLib类提供了解析曲线(直线.圆.椭圆.抛物线.双曲线)向解析曲面(平面.圆柱面.圆锥面.球面.圆环面)投影的功能,主要用来计算三维 ...
- Object-c Associated Object
oc的关联的作用在我看来就是将两个对象关联起来,用的时候通过key和对象把和这个对象关联的对象再取出来(我做的项目就是和UITableView里面的一个属性关联起来了) 举个栗子: - (void)v ...
- Numpy科学计算工具
Numpy初探 Numpy基础数据结构 Numpy数组是一个多维数组,称为ndarray.其由两部分组成: 实际的数据 描述这些数据的原数据 导入该库: import numpy as np 多维数组 ...
- 20.计算速度最快的valarray
#include <string> #include <iostream> //用于计算,计算的性能高于vector与array #include <valarray&g ...
- 如何配置MySQL?(三)
要进行mysql配置,首先要找到mysql的配置向导文件,这个配置向导文件就在我们安装目录下的一个bin的子目录下. 刚才我们是选择典型安装MySQL,一般windows是默认存储在C:\Progra ...
- NodeJS学习笔记 (11)网络UDP-dgram(ok)
模块概览 dgram模块是对UDP socket的一层封装,相对net模块简单很多,下面看例子. UPD客户端 vs UDP服务端 首先,启动UDP server,监听来自端口33333的请求. se ...
- [洛谷P1343]地震逃生
题目大意:有n个点m条单向边,每条边有一个容量.现有x人要分批从1走到n,问每批最多能走多少人,分几批运完(或输出无法运完). 解题思路:一看就是网络流的题目.每批最多能走多少人,即最大流.分几批运完 ...