zoukankan      html  css  js  c++  java
  • Codeforces 666E Forensic Examination SAM+权值线段树

    第一次做这种(SAM)带权值线段树合并的题 然而(zjq)神犇看完题一顿狂码就做出来了 (Orz)

    首先把所有串当成一个串建(SAM) 我们对(SAM)上每个点 建一棵权值线段树 每个叶子节点表示一个匹配串能到达这个点的子串个数 这样我们对最后的(SAM)的权值线段树按(parent)树合并 询问的时候找到对应的(SAM)上的权值线段树直接查询就好了

    具体的操作看代码吧~

    #include<bits/stdc++.h>
    using namespace std;
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define pa pair<int,int>
    #define mod 1000000007
    #define ll long long
    #define mk make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define cl(x) memset(x,0,sizeof x)
    #ifdef Devil_Gary
    #define bug(x) cout<<(#x)<<" "<<(x)<<endl
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #else
    #define bug(x)
    #define debug(...)
    #endif
    const int INF = 0x7fffffff;
    const int N=1230010;
    /*
    char *TT,*mo,but[(1<<15)+2];
    #define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
    inline int read(){
        int x=0,rev=0,ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return rev?-x:x;
    }
    pa operator * (const pa&A,const pa&B){return A.fi==B.fi?(A.se<B.se?A:B):(A.fi>B.fi?A:B);}
    pa operator + (const pa&A,const pa&B){return mk(A.fi+B.fi,A.se);}
    pa t[N*23];
    char s[N];
    int n,m,Q,c[N][27],par[N],len[N],fa[N][21],ls[N*23],rs[N*23],h[N],rt=1,sz=1,last=1,root[N],w[N],b[N],id; 
    void extend(int x){
    	int np=++sz,p=last;
    	len[np]=len[p]+1,last=np;
    	for(;p&&!c[p][x];p=par[p]) c[p][x]=np;
    	if(!p) par[np]=rt;
    	else{
    		int q=c[p][x];
    		if(len[p]+1==len[q]) par[np]=q;
    		else{
    			int nq=++sz;
    			len[nq]=len[p]+1,par[nq]=par[q],par[q]=par[np]=nq;
    			memcpy(c[nq],c[q],sizeof c[nq]);
    			for(;p&&c[p][x]==q;p=par[p]) c[p][x]=nq;
    		}
    	}
    }
    void modify(int&pos,int l,int r,int x){
    	if(!pos) pos=++id; 
    	if(l==r){
    		t[pos].fi++,t[pos].se=l;
    //		cout<<t[pos].fi<<" "<<t[pos].se<<endl;
    		return;
    	}
    	int mid=l+r>>1;
    	if(x<=mid) modify(ls[pos],l,mid,x);
    	else modify(rs[pos],mid+1,r,x);
    	t[pos]=t[ls[pos]]*t[rs[pos]];
    }
    inline int merge(int x,int y,int l,int r)
    {
        if (!x||!y) return x|y;	
        int z=++id;
        if (l==r) {
            t[z]=t[x]+t[y];
            return z;
        }
        int mid=(l+r)>>1;
        ls[z]=merge(ls[x],ls[y],l,mid),rs[z]=merge(rs[x],rs[y],mid+1,r);
        t[z]=t[ls[z]]*t[rs[z]];
        return z;
    }
    pa Query(int pos,int l,int r,int nl,int nr){
    	if(!pos) return mk(0,0);
    	if(nl<=l&&r<=nr) return t[pos];
    	int mid=l+r>>1;
    	if(nr<=mid) return Query(ls[pos],l,mid,nl,nr);
    	else if(nl>mid) return Query(rs[pos],mid+1,r,nl,nr);
    	else return Query(ls[pos],l,mid,nl,nr)*Query(rs[pos],mid+1,r,nl,nr);
    }
    void topsort(){
    	for(int i=1;i<=sz;i++) w[len[i]]++;
    	for(int i=1;i<=sz;i++) w[i]+=w[i-1];
    	for(int i=1;i<=sz;i++) b[w[len[i]]--]=i;
    	for(int i=sz;i;i--){
    		int j=b[i];
    		if(par[j]) root[par[j]]=merge(root[par[j]],root[j],1,n);
    	}
    }
    void get_fa(){
    	for(int i=1;i<=sz;i++) fa[i][0]=par[i];
    	for(int i=1;i<=20;i++) for(int j=1;j<=sz;j++) fa[j][i]=fa[fa[j][i-1]][i-1];
    }
    int get(int l,int r){
    	int L=r-l+1,x=h[r];
    	for(int i=20;~i;i--) if(len[fa[x][i]]>=L) x=fa[x][i];
    //	-len[par[x]]-len[par[fa[x][i]]]
    	return x;
    }
    int main(){
    #ifdef Devil_Gary
    	freopen("in.txt","r",stdin);
    #endif
    	scanf("%s",s+1),m=strlen(s+1);
    	for(int i=1;i<=m;i++) extend(s[i]-'a'),h[i]=last;
    	n=read();
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1),m=strlen(s+1),extend(26);
    		for(int j=1;j<=m;j++) extend(s[j]-'a'),modify(root[last],1,n,i);
    	}
    //	bug(sz);
    	topsort(),get_fa();
    	for(Q=read();Q;Q--){
    		int l=read(),r=read(),pl=read(),pr=read(),x=get(pl,pr);
    		pa ans=Query(root[x],1,n,l,r);
    		if(!ans.fi) printf("%d 0
    ",l);
    		else printf("%d %d
    ",ans.se,ans.fi);
    	} 
    }
    
    
    
  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9057102.html
Copyright © 2011-2022 走看看