zoukankan      html  css  js  c++  java
  • LOJ6041 SAM+set+树状数组

    首先对于原串建(SAM),我们可以发先在一个点(i)(right)集合里的点的相似度就是(len[i]),于是可以将(SAM)(right)集合通过(set)来启发式合并,每次加入新的点对((i,j,len[i])),最后离线询问二维数点就可以解决了

    但是这样每次维护(set)加入的点对是平方级别的的 我们可以发现对于一个要加入的点(i)只需要找(set)里和他相邻的两个点 将他们的点对加入就好 其余点对不会影响答案

    复杂度(O(nlog^2n))
    具体的看代码吧

    #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
    #define lowbit(x) x&(-x)
    const int INF = 0x7fffffff;
    const int N=2e5+5;
    /*
    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;
    }
    set<int>st[N];
    typedef set<int>::iterator iter;
    struct data{
    	int x,y,val;
    }t[N],a[N<<5];
    int lst,rt,n,m,sz,tot,ans[N],len[N],c[N][2],par[N],w[N],b[N],s[N];
    char ss[N]; 
    void extend(int x){
    	int np=++sz,p=lst;
    	len[np]=len[p]+1,lst=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[q]==len[p]+1) par[np]=q;
    		else{
    			int nq=++sz;
    			memcpy(c[nq],c[q],sizeof c[q]);
    			len[nq]=len[p]+1,par[nq]=par[q];
    			par[q]=par[np]=nq;
    			for(;p&&c[p][x]==q;p=par[p]) c[p][x]=nq;
    		}
    	}
    }
    void pre(){
    	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=sz;i;i--) b[w[len[i]]--]=i;
    	for(int i=sz;i>=2;i--){
    		int x=b[i],y=par[x];
    		if(st[x].size()>st[y].size()) swap(st[x],st[y]);
    		for(iter it=st[x].begin();it!=st[x].end();++it){
    //			iter w=lower_bound(st[y].begin(),st[y].end(),*it);
    			iter w=st[y].lower_bound(*it);
    			if(w!=st[y].end()) a[++tot]=(data){*it,*w,len[y]};
    			if(w!=st[y].begin()) a[++tot]=(data){*(--w),*it,len[y]};
    		}
    		for(iter it=st[x].begin();it!=st[x].end();it++) st[y].insert(*it);
    	} 
    }
    bool cmp(data a,data b){
    	return a.x>b.x;
    }
    void add(int x,int v){
    	for(int i=x;i<=n;i+=lowbit(i)) s[i]=max(s[i],v);
    } 
    int Query(int x){
    	int ans=0;
    	for(int i=x;i;i-=lowbit(i)) ans=max(ans,s[i]);
    	return ans;
    }
    int main(){
    #ifdef Devil_Gary
    	freopen("A7.in","r",stdin);
    #endif
    	n=read(),m=read(),rt=lst=sz=1,scanf("%s",ss+1); 
    	for(int i=1;i<=n;i++) extend(ss[i]-'0'),st[lst].insert(i);
    	for(int i=1;i<=m;i++) t[i].x=read(),t[i].y=read(),t[i].val=i;
    	pre(),sort(t+1,t+m+1,cmp),sort(a+1,a+tot+1,cmp);
    	for(int i=1,j=1;i<=m;i++){
    		for(;j<=tot&&a[j].x>=t[i].x;j++) add(a[j].y,a[j].val);
    		ans[t[i].val]=Query(t[i].y);
    	}
    	for(int i=1;i<=m;i++) printf("%d
    ",ans[i]); 
    }
    
  • 相关阅读:
    迭代器、生成器
    函数(函数基础、装饰器、递归、匿名函数)
    文件处理
    python对象、引用
    字符编码
    流程控制if、while、for
    编程与编程语言
    Java源码阅读(五)—— AbstractQueuedSynchronizer
    Java并发编程(二) —— volatile
    Java源码阅读(七)—— ReentrantReadWriteLock
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9115496.html
Copyright © 2011-2022 走看看