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]); 
    }
    
  • 相关阅读:
    android 75 新闻列表页面
    android 74 下载文本
    android 73 下载图片
    android 72 确定取消对话框,单选对话框,多选对话框
    android 71 ArrayAdapter和SimpleAdapter
    android 70 使用ListView把数据显示至屏幕
    maven如何将本地jar安装到本地仓库
    Centos6.7搭建ISCSI存储服务器
    解决maven打包编译出现File encoding has not been set问题
    MySQL 解决 emoji表情 的方法,使用utf8mb4 字符集(4字节 UTF-8 Unicode 编码)
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9115496.html
Copyright © 2011-2022 走看看