bzoj 2555 SubString——后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555
要维护 right 集合的大小。因为 fa 会变,且 fa 构成一棵树,所以考虑用 LCT 来维护……
和平常写的 LCT 不太一样。因为要的值是原树上子树里的值,所以没有 makeroot ,splay 里不维护 splay 里的子树信息,只维护加法标记,表示 link 一下就给原树的自己到根的那条链上的所有点加了自己的值。cut 就是减掉自己的值。所以 query 或者 splay 的时候先把自己这棵 splay 里自己到根的路径 pshd 一遍,且没有 pshp 什么的。而且 link 时要区分两个点哪个是原树上的父亲。
不知怎么看出字符只有大写字母的。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,K=,M=3e6+;
int cnt=,lst=,go[N][K],fa[N],l[N],mask;
int c[N][],pre[N],sta[N],top,sm[N],tg[N];
char ch[M];
void decodeWithMask(int n,int mask)
{
for(int i=;i<n;i++)
{
mask=(mask*+i)%n;
swap(ch[i],ch[mask]);
}
}
bool isroot(int x){return c[pre[x]][]!=x&&c[pre[x]][]!=x;}
void pshd(int x)
{
if(!tg[x])return;int ls=c[x][],rs=c[x][];
sm[ls]+=tg[x];tg[ls]+=tg[x];sm[rs]+=tg[x];tg[rs]+=tg[x];
tg[x]=;
}
void Pshd(int x)
{
sta[top=]=x;
for(;!isroot(x);x=pre[x])sta[++top]=pre[x];
for(int i=top;i;i--)pshd(sta[i]);
}
void rotate(int x)
{
int y=pre[x],z=pre[y];
if(!isroot(y))c[z][y==c[z][]]=x;
pre[x]=z;
int d=(x==c[y][]);
pre[c[x][!d]]=y; pre[y]=x;
c[y][d]=c[x][!d]; c[x][!d]=y;
}
void splay(int x)
{
Pshd(x);
while(!isroot(x))
{
int y=pre[x],z=pre[y];
if(!isroot(y))
{
if((y==c[z][])^(x==c[y][]))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
for(int t=;x;splay(x),c[x][]=t,t=x,x=pre[x]);
}
void link(int x,int y)
{
pre[y]=x;access(x);splay(x);
sm[x]+=sm[y]; tg[x]+=sm[y];//tg:pre of x all added
}
void cut(int x)
{
access(x);splay(x);
sm[c[x][]]-=sm[x]; tg[c[x][]]-=sm[x];//tg:pre of x all declined
pre[c[x][]]=; c[x][]=;
}
void add(int w)
{
int p=lst,np=++cnt;lst=np;l[np]=l[p]+;sm[np]=;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=,link(,np);
else
{
int q=go[p][w];
if(l[q]==l[p]+)fa[np]=q,link(q,np);
else
{
int nq=++cnt;l[nq]=l[p]+;
cut(q);link(fa[q],nq);link(nq,q);link(nq,np);///
fa[nq]=fa[q];fa[q]=nq;fa[np]=nq;//after link&cut !
memcpy(go[nq],go[q],sizeof go[q]);
for(;go[p][w]==q;p=fa[p])go[p][w]=nq;
}
}
}
int query(int len)
{
int cr=;
for(int i=;i<len;i++)
{
if(!go[cr][ch[i]-'A'+])return ;
cr=go[cr][ch[i]-'A'+];
}
Pshd(cr); return sm[cr];
}
int main()
{
int Q;scanf("%d",&Q);scanf("%s",ch);
int n=strlen(ch);for(int i=;i<n;i++)add(ch[i]-'A'+);
char tch[];
while(Q--)
{
scanf("%s",tch);scanf("%s",ch);n=strlen(ch);
decodeWithMask(n,mask);
if(tch[]=='A')
{
for(int i=;i<n;i++)add(ch[i]-'A'+);
}
else
{
int d=query(n);printf("%d\n",d);
mask^=d;
}
}
return ;
}
bzoj 2555 SubString——后缀自动机+LCT的更多相关文章
- bzoj 2555 SubString —— 后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...
- bzoj 2555: SubString 后缀自动机+LCT
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 688 Solved: 235[Submit][Status][Dis ...
- BZOJ 2555: SubString 后缀自动机_LCT
很水的一道题,就是有些细节没注意到. 比如说将调试信息误以为是最终结果而多调了20分钟QAQ ..... 我们注意到,每新加一个节点,改变的是该节点沿着 Parent 走一直走到根节点. 对应的,在 ...
- bzoj 2555 SubString(SAM+LCT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...
- 【BZOJ2555】SubString 后缀自动机+LCT
[BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2 ...
- bzoj 5408: string 后缀自动机 + LCT
联赛前练练码力. code: #include <vector> #include <cstdio> #include <cstring> #include < ...
- ●BZOJ 2555 SubString
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2555题解: 后缀自动机+LCT 不难发现,对于输入的询问串,在自动机里trans后的到的状态 ...
- bzoj 2555: SubString【后缀自动机+LCT】
一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...
- 字符串(LCT,后缀自动机):BZOJ 2555 SubString
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1620 Solved: 471 Description 懒得写背景了 ...
随机推荐
- java jvm内存管理/gc策略/参数设置
1. JVM内存管理:深入垃圾收集器与内存分配策略 http://www.iteye.com/topic/802638 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想 ...
- iOS开发小结 - 关于swift中#if DEBUG判断不执行的解决方案
在以前的OC项目中我们经常用#if DEBUG来判断是否是在DEBUG模式下调试代码,然后最近我用swift写的项目中发现#if DEBUG判断居然不管用了,多方查证为果的情况下终于找到了解决方案,希 ...
- sqlserver一般需求
1.创建一个函数:将用逗号分隔的字符串变成一个表的一列,这样就可以运用在select 语句的in中查询 create Function StrToTable(@str varchar()) Retur ...
- 一个问题:C#引用类型传参,说出你的答案
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { People p = new Peo ...
- Pandas重建索引
重新索引会更改DataFrame的行标签和列标签.重新索引意味着符合数据以匹配特定轴上的一组给定的标签. 可以通过索引来实现多个操作 - 重新排序现有数据以匹配一组新的标签. 在没有标签数据的标签位置 ...
- JT809 加密解密算法
平台对接标准上说“在数据包发送之前,二进制数据包与伪随机序列按字节进行异或运算.加密算法如下:用N模伪随机序列发生器产生伪随机字节序列.将待传输的数据与伪随机码按字节进行异或运算”下面代码是C语言的代 ...
- 【Demo】CSS3 3D转换
3D转换transform rotateX() 方法 rotateX()方法,围绕其在一个给定度数X轴旋转的元素. div { transform: rotateX(120deg); -webkit- ...
- flask bootstrap IE11的 兼容性问题
在子模板内添加如下代码确保IE11的兼容性问题. {% extends 'bootstrap/base.html' %}{% block metas %} <meta http-equiv=&q ...
- sql语句遇到错误: The used SELECT statements have a different number of columns :
这是因为使用union的两个SQL语句产生的记录的表结构不一致. 必须是结构完全一致的记录集合才可以使用UNION. 以上就是两个表的字段不一样,导致,所以大家可以检查下.
- HData——ETL 数据导入/导出工具
HData是一个异构的ETL数据导入/导出工具,致力于使用一个工具解决不同数据源(JDBC.Hive.HDFS.HBase.MongoDB.FTP.Http.CSV.Excel.Kafka等)之间数据 ...