关于毒瘤
查看原帖
关于毒瘤
125454
CLCA_楼主2020/8/13 19:53

A了这道题,祝你们成功

不知道本题卡空间还是写错了?写的可持久化线段树合并,有这么写过的大佬吗。

我猜放一百多行代码没人看惹.

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 1000005
using namespace std;
struct node{
	int l,r,sum;
	node(){l=r=sum=0;}
}a[N*30];
int tot;
int build(int l,int r,int pos){
	int x=++tot;a[x].sum=1;
	if(l==r)return x;
	int mid=(l+r)>>1;
	if(mid>=pos)a[x].l=build(l,mid,pos);
	else a[x].r=build(mid+1,r,pos);
	return x;
}
int merge(int x,int y,int l,int r){
	if(!x||!y)return x+y;
	int mid=(l+r)>>1,p=++tot;
	if(l==r){a[p].sum=a[x].sum+a[y].sum;return p;}
	a[p].l=merge(a[x].l,a[y].l,l,mid);
	a[p].r=merge(a[x].r,a[y].r,mid+1,r);
	a[p].sum=a[x].sum+a[y].sum;
	return p;
}
int ask(int x,int l,int r,int L,int R){
	if(!x)return 0;
	if(L<=l&&R>=r)return a[x].sum;
	int mid=(l+r)>>1,sum=0;
	if(mid>=L)sum+=ask(a[x].l,l,mid,L,R);
	if(mid<R)sum+=ask(a[x].r,mid+1,r,L,R);
	return sum;
}
int n;
struct SAM{
	int len[N],fa[N],nxt[N][26],rt[N],idx,pre,T,mat[N],b[N],c[N],del[N];
	SAM(){len[0]=idx=pre=T=0;fa[0]=~0;}
	void clean(int m){
		idx=pre=T=0;
		rep(i,0,(m<<1)){
			len[i]=fa[i]=rt[i]=mat[i]=b[i]=c[i]=del[i]=0;
			memset(nxt[i],0,sizeof(nxt[i]));fa[0]=~0;
		}
	}
	void extend(int ch,int type){
		int cur=++idx,p=pre;len[cur]=len[pre]+1;
		while(~p&&!nxt[p][ch])nxt[p][ch]=cur,p=fa[p];
		if(p==-1)fa[cur]=0;
		else{
			int q=nxt[p][ch];
			if(len[p]+1==len[q])fa[cur]=q;
			else{
				int now=++idx;len[now]=len[p]+1;
				rep(i,0,25)nxt[now][i]=nxt[q][i];
				fa[now]=fa[q];fa[q]=fa[cur]=now;
				while(~p&&nxt[p][ch]==q)nxt[p][ch]=now,p=fa[p];
			}
		}
		pre=cur;
		if(type)rt[cur]=build(1,n,++T);
		else mat[++T]=cur;
	}
	void init(){
		rep(i,1,idx)c[len[i]]++;
		rep(i,1,idx)c[i]+=c[i-1];
		rep(i,1,idx)b[c[len[i]]--]=i;
		pre(i,idx,1)rt[fa[b[i]]]=merge(rt[fa[b[i]]],rt[b[i]],1,n);
	}
	char s[N];
	bool check(int l,int r,int x,int ln){
		if(ln>(r-l+1))return false;
		return ask(rt[x],1,n,l+ln-1,r)?1:0;
	}
	void solve(){
		rep(i,1,idx)c[len[i]]++;
		rep(i,1,idx)c[i]+=c[i-1];
		rep(i,1,idx)b[c[len[i]]--]=i;
		long long ans=0;
		pre(i,idx,1){
			if(len[b[i]]>del[b[i]])ans+=(len[b[i]]-max(del[b[i]],len[fa[b[i]]]));
			del[fa[b[i]]]=max(del[fa[b[i]]],del[b[i]]);
		}//rep(i,1,idx)del[i]=0;
		printf("%lld\n",ans);
	}
}w,u;
char s[N];
void calc(){
	//cout<<"tt"<<endl;
	//cout<<"ss"<<endl;
	scanf("%s",s+1);
	int m=strlen(s+1);
	u.clean(m);
	rep(i,1,m)u.extend(s[i]-'a',0);
	//rep(i,1,m)printf("%d ",u.mat[i]);putchar('\n');
	int l,r;scanf("%d%d",&l,&r);
	int ln=0,now=0;
	rep(i,1,m){
		int op=s[i]-'a';
		while(now&&(!w.nxt[now][op]||!w.check(l,r,w.nxt[now][op],ln+1)))now=w.fa[now],ln=w.len[now];
		if(w.nxt[now][op]&&w.check(l,r,w.nxt[now][op],ln+1))now=w.nxt[now][op],ln++;
		//cout<<i<<" "<<ln<<endl;
		u.del[u.mat[i]]=ln;
	}
	u.solve();
}
int main(){
	//freopen("input","r",stdin);
	scanf("%s",s+1);
	n=strlen(s+1);
	rep(i,1,n)w.extend(s[i]-'a',1);
	//cout<<"ss"<<endl;
	w.init();
	//cout<<"tt"<<endl;
	int q;scanf("%d",&q);
	//cout<<"uu"<<endl;
	//cout<<n<<" "<<q<<" "<<s+1<<endl;
	while(q--)calc();
	return 0;
}
/*
g++ 4770.cpp -o a -Wall -std=c++11
*/
2020/8/13 19:53
加载中...