喜闻乐见的LCT+SAM

此题要求动态插入,直接上后缀树。然后询问其实就是求一个节点的子树后缀结束节点的个数。

因为建立后缀树需要插入和删除,就直接上LCT。每次加入一个点,把它到根的路径加一

(现在我才知道access之后那个splay就是这个点到根的路径,LCT学得不好)

思路不需要说太多,就是码量大。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=3001000;
int T,ans;
char s[N];
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int get(int ans){
cin>>s;
int len=strlen(s);
for (int j=0;j<len;j++) {
ans=(ans*131+j)%len;
char c=s[j];
s[j]=s[ans];
s[ans]=c;
}
return len;
}
struct lct{
int fa[N],ch[N][2],w[N],lazy[N],stack[N];
void add(int x,int y){
w[x]+=y;lazy[x]+=y;
}
void pushdown(int x){
if(lazy[x]){
add(ch[x][0],lazy[x]);add(ch[x][1],lazy[x]);
lazy[x]=0;
}
}
bool isroot(int x){
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
bool son(int x){
return ch[fa[x]][1]==x;
}
void rotate(int x){
int y=fa[x],z=fa[y],a=son(x),b=son(y),c=ch[x][!a];
if(!isroot(y))ch[z][b]=x;fa[x]=z;
if(c)fa[c]=y;ch[y][a]=c;
ch[x][!a]=y;fa[y]=x;
}
void splay(int x){
int top=1,a=x;stack[top]=a;
while(a)stack[++top]=a=fa[a];
while(top)pushdown(stack[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(isroot(y))rotate(x);
else{
if(son(x)==son(y))rotate(y);
else rotate(x);
rotate(x);
}
}
}
void access(int x){
for(int j=0;x;j=x,x=fa[x])
splay(x),ch[x][1]=j;
}
void link(int x,int f){
fa[x]=f;access(f);splay(f);add(f,w[x]);
}
void cut(int x){
access(x);splay(x);add(ch[x][0],-w[x]);
fa[ch[x][0]]=0;ch[x][0]=0;
}
}t;
struct SAM{
int tot,u,ln[N],size[N],trans[N][27],fa[N];
void ins(int c){
int x=++tot;ln[x]=ln[u]+1;size[x]=1;
t.w[x]=1;
for(;u&&trans[u][c]==0;u=fa[u])trans[u][c]=x;
if(u==0)fa[x]=1,t.link(x,1);
else{
int v=trans[u][c];
if(ln[v]==ln[u]+1)fa[x]=v,t.link(x,v);
else{
int w=++tot;
ln[w]=ln[u]+1;fa[w]=fa[v];
t.link(w,fa[w]);
memcpy(trans[w],trans[v],sizeof(trans[w]));
fa[x]=fa[v]=w;
t.cut(v);t.link(v,w);t.link(x,w);
for(;u&&trans[u][c]==v;u=fa[u])trans[u][c]=w;
}
}
u=x;
}
void add(){
int len=get(ans);
for(int i=0;i<len;i++)ins(s[i]-'A'+1);
}
int check(){
int len=get(ans);
int now=1;
for(int i=0;i<len;i++){
if(trans[now][s[i]-'A'+1]==0)return 0;
now=trans[now][s[i]-'A'+1];
}
t.splay(now);
return t.w[now];
}
}sam;
int main(){
T=read();
sam.tot=sam.u=1;
cin>>s;
int len=strlen(s);
for(int i=0;i<len;i++)sam.ins(s[i]-'A'+1);
while(T--){
cin>>s;
if(s[0]=='Q'){
int tmp=sam.check();
printf("%d\n",tmp);
ans^=tmp;
}
else sam.add();
}
return 0;
}

最新文章

  1. 适配ios9出现的问题:-canOpenURL: failed for URL
  2. 重磅开源:TN文本分析语言
  3. Joomla
  4. [转载]TFS体系结构和概念
  5. 简单好用的日志管理工具 Logrotate
  6. IDEA -14 注册码生成工具
  7. Oracle 10046 event详解-转载
  8. 20160405javaweb之jdbc
  9. vsftpd,tftp安装配置
  10. oc语言--BLOCK和协议
  11. Jmeter连接SqlServer数据库进行压力测试
  12. 在Android studio环境下使用EventBus
  13. English - Green Peanut Butter
  14. scrapy爬虫学习系列四:portia的学习入门
  15. JVM入门
  16. JavaScript操作和使用Cookie
  17. 【Excel】SUMIF函数的兼容性
  18. javadoc中{@link}与@see的简单使用以及区别
  19. HTML 标记 1
  20. 使用mysql workbench和vscode进行数据库差异比对

热门文章

  1. BZOJ 1176/2683 Mokia (三维偏序CDQ+树状数组)
  2. MySQL主从宕机的解决方法
  3. Proxifier安装与使用
  4. Vue经典开源项目
  5. 2015 Multi-University Training Contest 8 hdu 5389 Zero Escape
  6. 2015 Multi-University Training Contest 5 hdu 5349 MZL&#39;s simple problem
  7. 洛谷——P2822 组合数问题
  8. POJ 3088
  9. java语言中的多态概述
  10. linux下开发,解决cocos2d-x中编译出现的一个小问题, undefined reference to symbol &amp;#39;pthread_create@@GLIBC_2.2.5&amp;#39;