zoukankan      html  css  js  c++  java
  • bzoj 4556 字符串

    题目大意:

    一个字符串 $m$次询问

    每次询问$s[a:b]$的所有子串与$s[c:d]$的$lcp$最大值

    思路:

    因为有$lcp$ 考虑把串翻转转化为$lcs$

    建立后缀树,如何在树上通过$s[c:d]$查找是否存在$s[a:b]$的一个子串

    可以二分答案$x$,找到树上$d$点的最远的一个祖先满足其$maxlen ge x$,通过倍增实现

    在这个节点的所有$right$中若能找到$a+x-1$至$b$中的一个,则说明该答案可行

    实现$right$集合可以使用线段树合并,因为是儿子的后缀所以可以继承

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #define ll long long
    12 #define inf 2139062143
    13 #define MAXN 200100
    14 #define MOD 998244353
    15 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
    16 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
    17 #define ren for(register int i=fst[x];i;i=nxt[i])
    18 #define pb(i,x) vec[i].push_back(x)
    19 #define pls(a,b) (a+b)%MOD
    20 #define mns(a,b) (a-b+MOD)%MOD
    21 #define mul(a,b) (1LL*(a)*(b))%MOD
    22 using namespace std;
    23 inline int read()
    24 {
    25     int x=0,f=1;char ch=getchar();
    26     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    27     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    28     return x*f;
    29 }
    30 int n,m,tot,las,tr[MAXN][26],mxl[MAXN],fa[MAXN],pos[MAXN];
    31 char ch[MAXN];
    32 int fst[MAXN],nxt[MAXN],to[MAXN],cnt,f[MAXN][20],dep[MAXN];
    33 int rt[MAXN],num,ls[MAXN*20],rs[MAXN*20];
    34 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    35 int merge(int x,int y)
    36 {
    37     if(!(x*y)) return x|y;int z=++num;
    38     ls[z]=merge(ls[x],ls[y]),rs[z]=merge(rs[x],rs[y]);
    39     return z;
    40 }
    41 void mdf(int &k,int l,int r,int x)
    42 {
    43     if(!k) k=++num;if(l==r) return ;int mid=l+r>>1;
    44     if(x<=mid) mdf(ls[k],l,mid,x);
    45     if(x>mid) mdf(rs[k],mid+1,r,x);
    46 }
    47 int query(int k,int l,int r,int a,int b)
    48 {
    49     if(!k) return 0;if(l==a&&r==b) return 1;int mid=l+r>>1;
    50     if(b<=mid) return query(ls[k],l,mid,a,b);
    51     else if(a>mid) return query(rs[k],mid+1,r,a,b);
    52     else return query(ls[k],l,mid,a,mid)|query(rs[k],mid+1,r,mid+1,b);
    53 }
    54 void extend(int c,int x)
    55 {
    56     int p=las,np=las=++tot;mxl[np]=mxl[p]+1;mdf(rt[np],1,n,x);
    57     for(;p&&!tr[p][c];p=fa[p]) tr[p][c]=np;
    58     if(!p) {fa[np]=1;return ;}
    59     int q=tr[p][c];if(mxl[q]==mxl[p]+1) {fa[np]=q;return ;}
    60     int nq=++tot;mxl[nq]=mxl[p]+1;
    61     memcpy(tr[nq],tr[q],sizeof(tr[nq])); 
    62     fa[nq]=fa[q],fa[np]=fa[q]=nq;
    63     for(;p&&tr[p][c]==q;p=fa[p]) tr[p][c]=nq;
    64 }
    65 void dfs(int x,int pa)
    66 {
    67     dep[x]=dep[pa]+1,f[x][0]=pa;
    68     rep(j,1,19) if((1<<j)<=dep[x]) f[x][j]=f[f[x][j-1]][j-1];else break;
    69     ren dfs(to[i],x),rt[x]=merge(rt[x],rt[to[i]]);
    70 }
    71 int cheq(int x,int mx,int l,int r)
    72 {
    73     if(!mx) return 1;x=pos[x];
    74     dwn(i,19,0) if((1<<i)<=dep[x]&&mxl[f[x][i]]>=mx) x=f[x][i];
    75     return query(rt[x],1,n,l+mx-1,r);
    76 }
    77 int main()
    78 {
    79     n=read(),m=read();scanf("%s",ch+1);las=tot=1;int a,b,c,d,l,r,ans;
    80     dwn(i,n,1) extend(ch[i]-'a',n-i+1),pos[n-i+1]=las;
    81     rep(i,1,tot) add(fa[i],i);dfs(1,0);
    82     while(m--)
    83     {
    84         a=n-read()+1,b=n+1-read(),c=n+1-read(),d=n+1-read();
    85         swap(a,b);swap(c,d);l=0,r=min(b-a+1,d-c+1),ans=0;
    86         for(int mid=l+r>>1;l<=r;mid=l+r>>1)
    87             if(cheq(d,mid,a,b)) ans=mid,l=mid+1;
    88             else r=mid-1;
    89         printf("%d
    ",ans);
    90     }
    91 }
    View Code

    (这种线段树必须要新开点,因为有可能一个点$a$变成了另一个点$b$的儿子,在$c$合并到$b$时,$a$也被合并了

  • 相关阅读:
    安装 pptpd 服务
    profile bashrc bash_profile 之间的区别和联系
    11款基于Javascript的文件管理器
    C/C++学习之static_cast和dynamic_cast、reinterpret_cast
    VS.Net中程序集的Debug版本和Release版本的区别
    .net4.0以下的CookieContainer存在一个bug.即主域和子域cookie互访有问题。
    学习C# delegate和C# event
    使用log4net记录日志到数据库(含有自定义属性)
    c#获取本机ip地址|获取本机的本地上网IP地址
    Java 跨语言实现方案
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10509923.html
Copyright © 2011-2022 走看看