zoukankan      html  css  js  c++  java
  • 【Codeforces 666 E】—Forensic Examination(广义Sam+线段树合并)

    传送门

    考虑对所有串建出广义SamSam
    用线段树合并维护每个节点在哪些串中出现以及最大出现次数
    对于每个询问,先找到rr匹配到的节点
    然后树上倍增找到s[l,r]s[l,r]对应的节点
    在线段树上查询即可
    要特判这个串没有匹配的情况

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=50005;
    int m;
    namespace Seg{
    	cs int M=N*100;
    	#define mid ((l+r)>>1)
    	int lc[M],rc[M],mxpos[M],siz[M],tot;
    	inline void pushup(int u){
    		if(siz[lc[u]]<siz[rc[u]])siz[u]=siz[rc[u]],mxpos[u]=mxpos[rc[u]];
    		else siz[u]=siz[lc[u]],mxpos[u]=mxpos[lc[u]];
    	}
    	inline int copy(int u){
    		int now=++tot;lc[now]=lc[u],rc[now]=rc[u],mxpos[now]=mxpos[u],siz[now]=siz[u];return now;
    	}
    	void insert(int &u,int l,int r,int p){
    		u=copy(u);
    		if(l==r){siz[u]++,mxpos[u]=l;return;}
    		if(p<=mid)insert(lc[u],l,mid,p);
    		else insert(rc[u],mid+1,r,p);
    		pushup(u);
    	}
    	void merge(int &u,int r1,int r2,int l,int r){
    		if(!r1||!r2){u=r1+r2;return;}
    		u=++tot;
    		if(l==r){mxpos[u]=l,siz[u]=siz[r1]+siz[r2];return;}
    		merge(lc[u],lc[r1],lc[r2],l,mid);
    		merge(rc[u],rc[r1],rc[r2],mid+1,r);
    		pushup(u);
    	}
    	inline pii Merge(cs pii &a,cs pii &b){
    		return a.fi<b.fi?b:a;
    	}
    	pii query(int u,int l,int r,int st,int des){
    		if(!u)return pii(0,st);
    		if(st<=l&&r<=des)return pii(siz[u],mxpos[u]);
    		if(des<=mid)return query(lc[u],l,mid,st,des);
    		if(mid<st)return query(rc[u],mid+1,r,st,des);
    		return Merge(query(lc[u],l,mid,st,des),query(rc[u],mid+1,r,st,des));
    	}
    	#undef mid
    }
    namespace Sam{
    	cs int M=N<<1;
    	int tot=1,fa[M],len[M],nxt[M][26],rt[M];
    	vector<int> e[M];
    	inline int insert(int c,int last,int id){
    		if(nxt[last][c]&&len[nxt[last][c]]==len[last]+1){
    			Seg::insert(rt[nxt[last][c]],1,m,id);return nxt[last][c];
    		}
    		int cur=++tot,p=last,fg=0;
    		len[cur]=len[p]+1,Seg::insert(rt[cur],1,m,id);
    		for(;p&&!nxt[p][c];p=fa[p])nxt[p][c]=cur;
    		if(!p)fa[cur]=1;
    		else{
    			int q=nxt[p][c];
    			if(len[p]+1==len[q])fa[cur]=q;
    			else{
    				int clo=++tot;
    				len[clo]=len[p]+1,fa[clo]=fa[q];
    				if(len[clo]==len[cur])fg=1;
    				memcpy(nxt[clo],nxt[q],sizeof(nxt[q]));
    				for(;p&&nxt[p][c]==q;p=fa[p])nxt[p][c]=clo;
    				fa[cur]=fa[q]=clo;
    			}
    		}
    		return fg?tot:cur;
    	}
    	int f[M][20],pos[N*10],mt[N*10];
    	void dfs(int u){
    		f[u][0]=fa[u];
    		for(int i=1;i<=18;i++)f[u][i]=f[f[u][i-1]][i-1];
    		for(int &v:e[u]){
    			dfs(v);
    			Seg::merge(rt[u],rt[u],rt[v],1,m);
    		}
    	}
    	inline void getmatch(char *s){
    		int p=1,l=0;
    		for(int i=1,lim=strlen(s+1);i<=lim;i++){
    			int c=s[i]-'a';
    			while(p&&!nxt[p][c])p=fa[p],l=len[p];
    			if(!p)p=1,l=0;
    			if(nxt[p][c])p=nxt[p][c],l++;
    			pos[i]=p,mt[i]=l;
    		}
    	}
    	inline void build(char *s){
    		for(int i=2;i<=tot;i++)e[fa[i]].pb(i);
    		dfs(1);
    		getmatch(s);
    	}
    	inline void query(int l,int r,int pl,int pr){
    		int p=pos[pr];
    		if(mt[pr]<(pr-pl+1)){cout<<l<<" "<<0<<'
    ';return;}
    		for(int i=18;~i;i--)if(len[f[p][i]]>=pr-pl+1)p=f[p][i];
    		pii now=Seg::query(rt[p],1,m,l,r);
    		cout<<now.se<<" "<<now.fi<<'
    ';
    	}
    }
    char s[N*10];
    char ss[N];
    int n,q;
    int main(){
    	scanf("%s",s+1);
    	m=read();
    	for(int i=1;i<=m;i++){
    		scanf("%s",ss+1);
    		int last=1;
    		for(int j=1,len=strlen(ss+1);j<=len;j++)
    		last=Sam::insert(ss[j]-'a',last,i);
    	}
    	Sam::build(s);
    	q=read();
    	while(q--){
    		int l=read(),r=read(),pl=read(),pr=read();
    		Sam::query(l,r,pl,pr);
    	}
    }
    
  • 相关阅读:
    Linux机器学习软件配置
    安装linux14.04
    Navicat无法连接SqlServer数据库
    linux命令行安装teamviewer
    Ubuntu14.04+Dell 7060安装无线/有线网络驱动
    启动一个SpringBoot的maven项目
    HTML5新增特性
    HTML 表格|表单
    HTML 基础
    初识 wijmo-grid
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328402.html
Copyright © 2011-2022 走看看