zoukankan      html  css  js  c++  java
  • LOJ #6031. 「雅礼集训 2017 Day1」字符串

    (SAM) + 分类讨论

    先建出 (SAM) 然后求出 (|{ m endpos}(p)|)

    $ sum w=kqleq 10^5$,于是对 (k) 的大小分类讨论。

    (kgeqsqrt n)(qleqsqrt n) ,直接在 (SAM) 匹配 (w) ,求出每个位置在 (SAM) 上的点。对于每个询问,倍增向上跳到最靠上的且 ({ m len}(p) geq qr-ql+1) 的点 ,答案加上 (|{ m endpos}(p)|)

    这时 qleqslantsqrt{n}qn ,我们直接在 SAMSAM 暴力匹配 ww ,找出所有 ww 的前缀对应的节点,之后枚举询问,倍增跳到 w[l_i...r_i]w[l**i...r**i] 这个节点,将答案加上该节点的 endposendpo**s 集合大小即可。

    (k< sqrt n)(q>sqrt n) ,这时考虑 (qK^2) 的算法,我们可以开一个桶 (v[ql][qr]) 记录所有询问,并枚举 (w) 的所有前缀进行匹配,二分出它在 ([a,b]) 这段询问区间中出现的次数,乘上匹配长度加到答案中。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #define ll long long
    #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,D=350;
    int n,m,Q,K,tot=1,lst=1;
    int LL[N],RR[N],f[N][B+1];
    int fa[N],c[N][26],len[N],d[N],sz[N],mem[N];
    char s[N];
    inline void add(int ch) {
      R p=lst,np=lst=++tot;
      len[np]=len[p]+1,++sz[tot];
      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) return fa[np]=q,void();
      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 mp[N],ml[N];
    inline void solve1() {
      register ll ans;
      for(R i=1;i<=m;++i) LL[i]=g()+1,RR[i]=g()+1;
      while(Q--) {
        scanf("%s",s+1);
        R ql=g()+1,qr=g()+1;
        R p=1,l=0;
        for(R i=1;i<=K;++i) {
          R ch=s[i]-'a';
          while(p&&!c[p][ch]) p=fa[p],l=len[p];
          if(!p) {p=1,l=0,mp[i]=0; continue;}
          p=c[p][ch],++l,mp[i]=p,ml[i]=l;
        } ans=0;
        for(R i=ql,p,l,lim;i<=qr;++i) {
          p=mp[RR[i]],l=ml[RR[i]],lim=RR[i]-LL[i]+1;
          if(!p||l<lim) continue;
          for(R t=B;~t;--t) if(f[p][t]&&len[f[p][t]]>=lim)
            p=f[p][t];
          ans+=sz[p];
        } printf("%lld
    ",ans);
      }
    }
    vector<int> q[D][D];
    inline void solve2() {
      register ll ans=0;
      for(R i=1,l,r;i<=m;++i) 
        l=g()+1,r=g()+1,q[l][r].push_back(i);
      while(Q--) {
        ans=0;
        scanf("%s",s+1);
        R ql=g()+1,qr=g()+1;
        for(R i=1;i<=K;++i) for(R j=i,p=1;j<=K;++j) {
          p=c[p][s[j]-'a']; if(!p) break;
          ans+=1ll*(upper_bound(q[i][j].begin(),q[i][j].end(),qr)-
                    lower_bound(q[i][j].begin(),q[i][j].end(),ql))*sz[p];
        } printf("%lld
    ",ans);
      }  
    }
    inline void main() {
      n=g(),m=g(),Q=g(),K=g();
      scanf("%s",s+1);
      for(R i=1;i<=n;++i) add(s[i]-'a');
      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) sz[fa[mem[i]]]+=sz[mem[i]];
      for(R i=1;i<=tot;++i) f[i][0]=fa[i];
      for(R t=1;t<=B;++t) for(R i=1;i<=tot;++i)
        f[i][t]=f[f[i][t-1]][t-1];
      if(K>=sqrt(n)) solve1();
      else solve2();
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.10

  • 相关阅读:
    jconsole远程连接监控tomcat
    Nginx监控配置
    Nginx安装+2tomcat配置
    Flexbox布局模式的理解
    Web性能优化:图片优化
    大公司里怎样开发和部署前端代码?
    原生js下拉刷新
    全国三级城市联动 js版
    js获取智能机浏览器版本信息
    JS年月日三级联动下拉框日期选择代码
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12177585.html
Copyright © 2011-2022 走看看