zoukankan      html  css  js  c++  java
  • Codeforces 666E. Forensic Examination

    Description

    给出串 (S) ,和 (m) 个串 (T_i) ,每次询问 ((l,r,pl,pr)) 表示 (S[pl...pr])(T[l...r]) 中哪一个出现次数最多,求出现次数和编号
    题面

    Solution

    基础题...
    对于 (S,T[l...r]) 放在一起建广义后缀自动机
    然后每次倍增到 S[pl,pr] ,然后查询子树内出现次数最多的 (T) 即可
    我们可以开一棵 ([1,m]) 的线段树,维护每一个 (T) 的出现次数,维护最大值和最大值位置
    线段树合并上来就好了

    #include<bits/stdc++.h>
    using namespace std;
    template<class T>void gi(T &x){
    	int f;char c;
    	for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    	for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
    }
    const int N=1100010;
    int n,m,Q,ch[N][26],cur=1,cnt=1,len[N],fa[N],pos[N],rt[N];char s[N];
    int head[N],nxt[N],to[N],num=0,pa[N][20],tt=0,ls[N*20],rs[N*20];
    inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    inline void ins(int c){
    	int p=cur;cur=++cnt;len[cur]=len[p]+1;
    	for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
    	if(!p)fa[cur]=1;
    	else{
    		int q=ch[p][c];
    		if(len[p]+1==len[q])fa[cur]=q;
    		else{
    			int nt=++cnt;len[nt]=len[p]+1;
    			memcpy(ch[nt],ch[q],sizeof(ch[nt]));
    			fa[nt]=fa[q];fa[cur]=fa[q]=nt;
    			for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
    		}
    	}
    }
    struct data{int w,p;}tr[N*20];
    inline data upd(data x,data y){
    	if(x.w>=y.w)return x;
    	return y;
    }
    inline int merge(int x,int y){
    	if(!x||!y)return x+y;int o=++tt;
    	if(!ls[x] && !rs[x]){
    		tr[o].w=tr[x].w+tr[y].w;tr[o].p=tr[x].p;
    		return o;
    	}
    	ls[o]=merge(ls[x],ls[y]);
    	rs[o]=merge(rs[x],rs[y]);
    	tr[o]=upd(tr[ls[o]],tr[rs[o]]);
    	return o;
    }
    inline void mdf(int &x,int l,int r,int sa){
    	if(!x)x=++tt;
    	if(l==r){tr[x].w++;tr[x].p=l;return ;}
    	int mid=(l+r)>>1;
    	if(sa<=mid)mdf(ls[x],l,mid,sa);
    	else mdf(rs[x],mid+1,r,sa);
    	tr[x]=upd(tr[ls[x]],tr[rs[x]]);
    }
    inline void dfs(int x){
    	for(int i=1;i<=19;i++)pa[x][i]=pa[pa[x][i-1]][i-1];
    	for(int i=head[x];i;i=nxt[i])dfs(to[i]),rt[x]=merge(rt[x],rt[to[i]]);
    }
    inline int lca(int x,int k){
    	for(int i=19;i>=0;i--)if(len[pa[x][i]]>=k)x=pa[x][i];
    	return x;
    }
    inline data qry(int x,int l,int r,int sa,int se){
    	if(sa<=l && r<=se)return tr[x];
    	int mid=(l+r)>>1;
    	if(se<=mid)return qry(ls[x],l,mid,sa,se);
    	if(sa>mid)return qry(rs[x],mid+1,r,sa,se);
    	return upd(qry(ls[x],l,mid,sa,mid),qry(rs[x],mid+1,r,mid+1,se));
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      scanf("%s",s+1);n=strlen(s+1);
      for(int i=1;i<=n;i++)ins(s[i]-'a'),pos[i]=cur;
      cin>>m;
      for(int i=1;i<=m;i++){
    	  scanf("%s",s+1);cur=1;
    	  for(int j=1,len=strlen(s+1);j<=len;j++)
    		  ins(s[j]-'a'),mdf(rt[cur],1,m,i);
      }
      for(int i=2;i<=cnt;i++)link(fa[i],i),pa[i][0]=fa[i];
      dfs(1);
      int x,y,l,r;
      cin>>Q;
      while(Q--){
    	  gi(l);gi(r);gi(x);gi(y);
    	  x=lca(pos[y],y-x+1);
    	  data t=qry(rt[x],1,m,l,r);
    	  if(t.w)printf("%d %d
    ",t.p,t.w);
    	  else printf("%d 0
    ",l);
      }
      return 0;
    }
    
    
  • 相关阅读:
    css水平垂直居中
    JavaScript提供了哪几种“异步模式”?
    sort()
    后端开发中,可以在Cache-Control设置的常用指令
    纯函数
    react和vue
    npm(classnames) 更灵活使用类名
    shell知多少?
    常见的HTTP状态码
    axios
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9098887.html
Copyright © 2011-2022 走看看