ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P5212 SubString

2021-04-02 22:33:51  阅读:144  来源: 互联网

标签:AC 自动机 P5212 luogu SubString 动态 include 虚子 define


题面传送门
写了一个晚上才写完+调完,AC那一刻感觉神清气爽。
询问某一个串在另一个串内出现了几次想到AC自动机,但是因为强制在线而AC自动机无法动态更新fail树所以考虑SAM
然后发现我们只要动态维护LCT虚子树大小即可。
然而虚子树大小其实挺难维护的,所以可以改成每个点的链加。
时间复杂度\(O(nlogn)\)
code:

#include<cstdio>
#include<cstring>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define beg(x) int cur=s.h[x]
#define end cur
#define go cur=tmp.z
#define l(x) x<<1
#define r(x) x<<1|1
#define N 6000039
#define ll long long
#define ui unsigned int
using namespace std;
int n,m,k,mask,now;char a[N],_s[N];
struct linkcuttree{
	int fa[N],l[N],r[N],flag[N],st[N],sh,f[N],g[N],now,i;
	I void swap(int &x,int &y){x^=y^=x^=y;}
	I void pushr(int x){x&&(swap(l[x],r[x]),flag[x]^=1);}
	I void pushf(int x,int y){x&&(f[x]+=y,g[x]+=y);}
	I void pushdown(int x){flag[x]&&(pushr(l[x]),pushr(r[x]),flag[x]=0);g[x]&&(pushf(l[x],g[x]),pushf(r[x],g[x]),g[x]=0);}
	I int child(int x){return l[fa[x]]==x||r[fa[x]]==x;}
	I int wrt(int x){return l[fa[x]]==x;}
	I void rotate(int x){
		int y=fa[x],z=fa[y],b=(x^l[y]?l[x]:r[x]);child(y)&&((y^l[z]?r[z]:l[z])=x);
		x^l[y]?(l[x]=y,r[y]=b):(r[x]=y,l[y]=b);fa[x]=z;fa[y]=x;b&&(fa[b]=y);
	}
	I void splay(int x){
		int y=x;st[sh=1]=x;while(child(y)) st[++sh]=y=fa[y];while(sh) pushdown(st[sh--]);
		while(child(x)) child(fa[x])&&(rotate(wrt(x)^wrt(fa[x])?x:fa[x]),0),rotate(x);
	}
	I void access(int x){for(int y=0;x;x=fa[y=x]) splay(x),r[x]=y;}
	I void makeroot(int x){access(x);splay(x);pushr(x);}
	I void link(int x,int y){makeroot(x);fa[x]=y;}
	I void split(int x,int y){makeroot(y);access(x);splay(x);}
	I void cut(int x,int y){split(x,y);pushdown(x);l[x]=fa[y]=0;}
	I void dfs(int x){if(!x) return;pushdown(x);dfs(l[x]);dfs(r[x]);}
}s;
struct SAM{
	int fa[N],len[N],son[N][2],cnt=1,last=1,now,p,cur,pus,w[N];
	I void makefa(int x,int y){fa[x]&&(s.cut(x,fa[x]),0),s.link(x,y),fa[x]=y,w[x]&&(s.split(1,x),s.pushf(1,1),0);}
	I void insert(int x){
		p=last;now=last=++cnt;w[now]=1;len[now]=len[p]+1;while(p&&!son[p][x]) son[p][x]=now,p=fa[p];
		if(!p) return  makefa(now,1);
		cur=son[p][x];if(len[p]+1==len[cur]) makefa(now,cur);
		else{
			len[pus=++cnt]=len[p]+1;makefa(pus,fa[cur]);memcpy(son[pus],son[cur],sizeof(son[pus]));
			makefa(now,pus);int t=w[cur];w[cur]=0;makefa(cur,pus);w[cur]=t;s.f[pus]+=s.f[cur];while(p&&son[p][x]==cur) son[p][x]=pus,p=fa[p];
		}
	}
}gs;
I void make(char *s){char t;now=mask;for(int i=1;i<=m;i++)now=(now*131+i-1)%m,t=s[i],s[i]=s[now+1],s[now+1]=t;}
int main(){
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	register int i;
	scanf("%d",&n);scanf("%s",a+1);m=strlen(a+1);for(i=1;i<=m;i++) gs.insert(a[i]-'A');
	while(n--){
		scanf("%s",_s+1);scanf("%s",a+1);m=strlen(a+1);make(a);
		if(_s[1]=='A'){
			for(i=1;i<=m;i++)gs.insert(a[i]-'A');
		}
		else{
			now=1;for(i=1;i<=m;i++)now=gs.son[now][a[i]-'A'];
			now&&(s.access(now),s.splay(now),0);mask^=s.f[now];printf("%d\n",s.f[now]);
		}
	}
}

标签:AC,自动机,P5212,luogu,SubString,动态,include,虚子,define
来源: https://www.cnblogs.com/275307894a/p/14612615.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有