zoukankan      html  css  js  c++  java
  • Luogu P4094 [HEOI2016/TJOI2016]字符串

    题意:给定 (S) ,多组询问,每次 (a,b,c,d) 四个参数,问你子串 (S[a..b]) 的所有子串和 (S[c..d]) 的最长公共前缀的长度的最大值是多少。

    (SAM) + 线段树合并 + 二分答案

    二分答案 (md) 找到 (s[c+md-1])(SAM) 上对应的状态并倍增跳到一个最靠上的 ({ m maxlen}(p)geq md) 的状态,然后查找是否存在一个位置 $posin [a+md-1,b] && posin { m endpos}(p) $

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=200010,B=17,L=50;
    int n,m,lst=1,tot=1;
    char s[N];
    int c[N][26],fa[N],len[N],d[N],mem[N],f[N][B+1],rw[N];
    inline void add(int ch) {
      R p=lst,np=lst=++tot;
      len[np]=len[p]+1;
      while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
      if(!p) return fa[np]=1,void();
      R q=c[p][ch];
      if(len[q]==len[p]+1) fa[np]=q;
      else {
        R nq=++tot;
        memcpy(c[nq],c[q],26<<2);
        fa[nq]=fa[q],len[nq]=len[p]+1;
        fa[np]=fa[q]=nq;
        while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
      }
    }
    int cnt,sum[N*L],ls[N*L],rs[N*L],rt[N];
    inline void change(int& tr,int l,int r,int p) {
      if(!tr) tr=++cnt; ++sum[tr]; 
      if(l==r) return ; R md=(l+r)>>1;
      p<=md?change(ls[tr],l,md,p):change(rs[tr],md+1,r,p);
    }
    inline bool query(int tr,int l,int r,int LL,int RR) {
      if(LL<=l&&r<=RR) return sum[tr]; R md=(l+r)>>1;
      return (LL<=md&&ls[tr]&&query(ls[tr],l,md,LL,RR))
            ||(RR>md&&rs[tr]&&query(rs[tr],md+1,r,LL,RR));
    }
    inline int merge(int tr,int t,int l,int r) {
      if(!tr||!t) return tr+t;
      R p=++cnt,md=(l+r)>>1;
      sum[p]=sum[tr]+sum[t];
      if(l==r) return p;
      ls[p]=merge(ls[tr],ls[t],l,md);
      rs[p]=merge(rs[tr],rs[t],md+1,r);
      return p;
    }
    inline bool ck(int a,int b,int c,int d,int md) {
      R p=rw[c+md-1];
      for(R t=B;~t;--t) 
        if(f[p][t]&&len[f[p][t]]>=md) p=f[p][t];
      return query(rt[p],1,n,a+md-1,b);
    }
    inline void main() {
      n=g(),m=g(),scanf("%s",s+1),rw[0]=1;
      for(R i=1;i<=n;++i) 
        add(s[i]-'a'),change(rt[rw[i]=lst],1,n,i);
      for(R i=1;i<=tot;++i) ++d[len[i]];
      for(R i=1;i<=n;++i) d[i]+=d[i-1];
      for(R i=1;i<=tot;++i) mem[d[len[i]]--]=i;
      for(R i=tot;i;--i) {
        R u=mem[i]; f[u][0]=fa[u];
        rt[fa[u]]=merge(rt[fa[u]],rt[u],1,n);
      } 
      for(R t=1;t<=B;++t) for(R i=1;i<=tot;++i) 
        f[i][t]=f[f[i][t-1]][t-1];
      for(R i=1,a,b,c,d;i<=m;++i) {
        a=g(),b=g(),c=g(),d=g();
        R l=0,r=min(b-a+1,d-c+1),md;
        while(l<r) {
          md=(l+r+1)>>1;
          if(ck(a,b,c,d,md)) l=md;
          else r=md-1;
        } printf("%d
    ",l);
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.10

  • 相关阅读:
    STP生成树协议
    Fiddler快速入门(还有一个功能就是不经过网络,直接模拟一个响应返回给客户端)
    Qt宏Q_OBJECT展开记录
    rem_taobaofix.js
    yield return
    NET full stack framework
    API 网关
    Redis主从高可用缓存
    数据异构解决方案缓存一致性和跨服务器查询
    NET Core 防止跨站请求
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12177594.html
Copyright © 2011-2022 走看看