zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    强连通分量填坑记
    Car的旅行路线
    油滴扩散
    【转】孔乙已
    [CQOI2007]余数求和
    树形dp入门两题
    一本通 3.1 例 1」黑暗城堡
    一点点有的没的和一年总结
    leetcode答案 有效的括号(python)
    leetcode数据库题目及答案汇总
  • 原文地址:https://www.cnblogs.com/gary-2005/p/14331886.html
Copyright © 2011-2022 走看看