SPOJ COT 4 题解

SPOJ COT 4 题解

题目传送门

将s,t都反向,然后二分。

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=300000+233;
vector<int> tree[MAXN];
const int MAXLEN=1e5+20;
struct state{
	int len,link,minlen;
	unordered_map<char,int> ch;
};
struct SAM{
	int sz=0;
	state st[MAXLEN+MAXLEN];
	void sam_init(){
		st[0].len=0;
		st[0].link=-1;
		sz=0;
	}
	SAM(){
		sam_init();
	}
	int sam_extend(char c,int last){
		if(st[last].ch.find(c)!=st[last].ch.end()){
			return st[last].ch[c];
		}
		int cur=++sz;
		st[cur].len=st[last].len+1;
		int p=last;
		while(p!=-1&&st[p].ch.find(c)==st[p].ch.end()){
			st[p].ch[c]=cur;
			p=st[p].link;
		}
		if(p==-1){
			st[cur].link=0;
		}
		else{
			int q=st[p].ch[c];
			if(st[q].len==st[p].len+1){
				st[cur].link=q;
			}
			else{
				int clone;
				clone=++sz;
				st[clone].len=st[p].len+1;
				st[clone].ch=st[q].ch;
				st[clone].link=st[q].link;
				while(p!=-1&&st[p].ch.find(c)!=st[p].ch.end()&&st[p].ch[c]==q){
					st[p].ch[c]=clone;
					p=st[p].link;
				}
				st[cur].link=st[q].link=clone;
			}
		}
		return cur;
	}
	void gettree(){
		rb(i,1,sz) tree[st[i].link].PB(i);
	}
}sam;
int cnt;
int son[MAXN][26],fa[MAXN],belong[MAXN],is[MAXN],stay[MAXN],val[MAXN],anc[MAXN][32][4],depth[MAXN];
vector<mp> failtree[MAXN];
void lab(int now){
	for(auto it:tree[now]){
		lab(it);
		if(!belong[now]) belong[now]=belong[it];
	}
}
int getanc(int now,int k){
	if(k>depth[now]) return -1;
	rep(i,4){
		now=anc[now][k&31][i];
		k>>=5;
	}
	return now;
}
void buildanc(){
	rb(i,1,cnt) rep(k,4) anc[i][0][k]=i;
	rb(j,1,31) rb(i,1,cnt) anc[i][j][0]=anc[fa[i]][j-1][0];
	rb(k,1,3) rb(i,1,cnt) rb(j,1,31){
		if(j==1){
			anc[i][1][k]=anc[anc[i][16][k-1]][16][k-1];
		}
		else{
			anc[i][j][k]=anc[anc[i][j-1][k]][1][k];
		}
	}
}
void gao(int now){
	for(auto it:tree[now]) gao(it);
	for(auto it:tree[now]){
		failtree[now].PB({val[getanc(belong[it],sam.st[now].len)],it});
	}
}
int tot=0,tmprank[MAXN];
void my_sort(int now){
	sort(ALL(failtree[now]));
	tmprank[now]=++tot;
	for(auto it:failtree[now]){
		my_sort(it.SEC);
	}
}
int rnk[MAXN],sa[MAXN];
void my_sort(){
	sam.gettree();
	lab(0);
	gao(0);
	my_sort(0);
	vector<int> use;
	rb(i,0,cnt) use.PB(tmprank[is[i]]);
	sort(ALL(use));
	rb(i,0,cnt){
		rnk[i]=lower_bound(ALL(use),tmprank[is[i]])-use.begin()+1,sa[rnk[i]]=i;
//		cout<<rnk[i]<<"!
";
	}
}
mp range[300000+20];
mp crange[26];
int ans[300000+20];
int Len[300000+20];
vector<pair<int,mp> > query[MAXN];
int lowbound(int l,int r,int x,int lent){
	if(rnk[getanc(sa[l],lent)]>=x){
		return l;
	}
	if(rnk[getanc(sa[r],lent)]<x){
		return r+1;
	}
	while(l<r){
		int mid=(l+r)>>1;
		int anc=getanc(sa[mid],lent);
		if(rnk[anc]>=x){
			r=mid;
		}
		else{
			l=mid+1;
		}
	}
	return l;
}
mp merge(mp A,mp B,int lent){
	if(A.FIR==INF||B.FIR==INF) return {INF,-INF};
	mp ret;
	ret.FIR=lowbound(A.FIR,A.SEC,B.FIR,lent);//找到第一个>=x的位置 
	ret.SEC=lowbound(A.FIR,A.SEC,B.SEC+1,lent);
	ret.SEC--;
	if(ret.FIR>ret.SEC) ret={INF,-INF};
	return ret;
}
int bit[MAXN+1];
void add(int pos,int val=1){
	while(pos<=MAXN){
		bit[pos]+=val;
		pos+=pos&(-pos);
	}
}
int quey(int pos){
	int ret=0;
	while(pos){
		ret+=bit[pos];
		pos-=pos&(-pos);
	}
	return ret;
}
int quey(int l,int r){
	return quey(r)-quey(l-1);
}
void goanswer(int now){
	add(rnk[now]);
	for(auto it:query[now]){
		if(it.SEC.FIR==1||it.SEC.FIR>it.SEC.SEC){
			continue;
		}
		ans[it.FIR]=quey(it.SEC.FIR,it.SEC.SEC);
	}
	rep(i,26) if(son[now][i]) goanswer(son[now][i]);
	add(rnk[now],-1);
}
int main(){
	int Q;
	scanf("%d",&Q);
	vector<pair<int,mp> > ope;
	stay[1]=0;
	int n=1;
	rb(i,1,Q){
		int ty;
		scanf("%d",&ty);
		if(ty==1){
			int si;
			char c;
			scanf("%d",&si);
			cin>>c;
			++n;
			if(son[stay[si]][c-'a']);
			else{
				son[stay[si]][c-'a']=++cnt;
				fa[cnt]=stay[si];
				val[cnt]=c-'a';
				depth[cnt]=depth[fa[cnt]]+1;
			}
			stay[n]=son[stay[si]][c-'a'];
		}
		if(ty==2){
			int x,ti;
			char c;
			scanf("%d%d",&x,&ti),cin>>c;
			ope.PB({x,{ti,c-'a'}});
		}
		if(ty==3){
			int ti,tj;
			scanf("%d%d",&ti,&tj);
			ope.PB({ty,{ti,tj}}); 
		}
		if(ty==4){
			int ti,si;
			scanf("%d%d",&ti,&si);
			ope.PB({ty,{ti,si}});
		}
	}
	rb(i,1,cnt) is[i]=sam.sam_extend(val[i]+'a',is[fa[i]]),belong[is[i]]=i;
	buildanc();
	my_sort();
	range[1]={1,n};
	rep(i,26) crange[i]={INF,-INF};
	rb(i,1,cnt){
		check_min(crange[val[i]].FIR,rnk[i]);
		check_max(crange[val[i]].SEC,rnk[i]);
	}
	int Que=0;
	n=1;
	for(auto it:ope){
		if(it.FIR==0){
			range[++n]=merge(range[it.SEC.FIR],crange[it.SEC.SEC],Len[it.SEC.FIR]);
			Len[n]=Len[it.SEC.FIR]+1;
		}
		if(it.FIR==1){
			range[++n]=merge(crange[it.SEC.SEC],range[it.SEC.FIR],1);
			Len[n]=Len[it.SEC.FIR]+1;
		}
		if(it.FIR==3){
			range[++n]=merge(range[it.SEC.SEC],range[it.SEC.FIR],Len[it.SEC.SEC]);
			Len[n]=Len[it.SEC.FIR]+Len[it.SEC.SEC];
			check_min(Len[n],1000000000); 
		}
		if(it.FIR==4){
			Que++;
			query[stay[it.SEC.SEC]].PB({Que,range[it.SEC.FIR]});
		}
	}
	goanswer(0);
	rb(i,1,Que){
		printf("%d
",ans[i]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/gary-2005/p/14331886.html