• BZOJ3230 相似子串[后缀数组+二分+st表]


    BZOJ3230 相似子串

    给一个串,查询排名i和j的子串longest common suffix和longest common prefix

    思路其实还是蛮好想的,就是码起来有点恶心。可以发现后缀拍完序之后的子串可以根据sa自前而后的顺序标子串排名,和统计不同字串那里差不多,自lcp后的是新子串,开始标记排名。实际操作时在每个后缀上标这一后缀开始第一个新子串排名,可证是单调增的,然后查询就二分查出子串开始的后缀也就是位置啦,然后用st表维护子串(所在后缀的)lcp即可。lcs的话就把串反转一下做个排序同理st表维护RMQ。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=100000+7,Log=20;
     5 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
     6 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
     7 template<typename T>inline void read(T&x){
     8     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
     9     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();f?x-=x:1;
    10 }
    11 char s[2][N];
    12 int po[N],n,q,a,b,h1,r1,h2,r2,l1,l2;
    13 ll q1,q2;
    14 
    15 int cnt[2][N],h[2][N],sa[2][N],rk[2][N],y[2][N],m,p;
    16 inline void suffix_sort(int l){ m=127,p=0;
    17     for(register int i=1;i<=n;++i)++cnt[l][rk[l][i]=s[l][i]];
    18     for(register int i=1;i<=m;++i)cnt[l][i]+=cnt[l][i-1];
    19     for(register int i=n;i;--i)sa[l][cnt[l][rk[l][i]]--]=i;
    20     for(register int k=1;k<n;k<<=1,p=0){
    21         for(register int i=n-k+1;i<=n;++i)y[l][++p]=i;
    22         for(register int i=1;i<=n;++i)if(sa[l][i]>k)y[l][++p]=sa[l][i]-k;
    23         for(register int i=1;i<=m;++i)cnt[l][i]=0;
    24         for(register int i=1;i<=n;++i)++cnt[l][rk[l][y[l][i]]];
    25         for(register int i=1;i<=m;++i)cnt[l][i]+=cnt[l][i-1];
    26         for(register int i=n;i;--i)sa[l][cnt[l][rk[l][y[l][i]]]--]=y[l][i];
    27         swap(rk,y);rk[l][sa[l][1]]=p=1;
    28         for(register int i=2;i<=n;++i)rk[l][sa[l][i]]=y[l][sa[l][i-1]]==y[l][sa[l][i]]&&y[l][sa[l][i-1]+k]==y[l][sa[l][i]+k]?p:++p;
    29         if(p==n)break;m=p;
    30     }p=0;
    31     for(register int i=1;i<=n;h[l][rk[l][i]]=p,p?--p:1,++i)while(s[l][i+p]==s[l][sa[l][rk[l][i]-1]+p]&&++p);
    32 }
    33 
    34 ll rank[N],tot=1;
    35 inline void mark(){for(register int i=1;i<=n;++i)rank[i]=tot,tot+=n-sa[0][i]+1-h[0][i];--tot;}
    36 struct st_table{
    37     int lcp[N][Log];
    38     inline void build(int l){
    39         for(register int i=1;i<=n;++i)lcp[i][0]=h[l][i];
    40         for(register int k=1;k<=po[n];++k)for(register int i=1;i<=n+1-(1<<k);++i)
    41         lcp[i][k]=_min(lcp[i][k-1],lcp[i+(1<<(k-1))][k-1]);
    42     }
    43     inline int RMQ(int l,int r){return _min(lcp[l][po[r-l+1]],lcp[r-(1<<po[r-l+1])+1][po[r-l+1]]);}
    44 }pos,neg;//positive,negative
    45 
    46 int main(){//freopen("tmp.txt","r",stdin);
    47     read(n),read(q),scanf("%s",s[0]+1);
    48     for(register int i=2;i<=n;++i)po[i]=(i-1)==(1<<(po[i-1]+1))?po[i-1]+1:po[i-1];
    49     for(register int i=1;i<=n;++i)s[1][i]=s[0][n-i+1];
    50     suffix_sort(0),suffix_sort(1),mark();
    51     pos.build(0),neg.build(1);
    52 //    for(register int i=1;i<=n;++i)cerr<<s[1][i];puts("");
    53 //    for(register int i=1;i<=n;++i)cerr<<i<<" "<<rk[1][i]<<" "<<sa[1][i]<<endl;
    54     for(register int i=1;i<=q;++i){
    55         read(q1),read(q2);
    56         if(q1>tot||q2>tot){printf("-1
    ");continue;}
    57         h1=upper_bound(rank+1,rank+n+1,q1)-rank-1,h2=upper_bound(rank+1,rank+n+1,q2)-rank-1;
    58         l1=sa[0][h1],l2=sa[0][h2],r1=l1+h[0][h1]+q1-rank[h1],r2=l2+h[0][h2]+q2-rank[h2];
    59         if(h1==h2)a=_min(r1,r2)-l1+1;
    60         else{
    61             if(h1>h2)h1^=h2^=h1^=h2;
    62             a=pos.RMQ(h1+1,h2);if((a>r1-l1+1)||(a>r2-l2+1))a=_min(r1-l1+1,r2-l2+1);
    63         }//get a.
    64         h1=rk[1][n-r1+1],h2=rk[1][n-r2+1];//cerr<<l1<<" "<<r1<<" "<<l2<<" "<<r2<<" "<<h1<<" "<<h2<<endl;
    65         if(h1==h2)b=r1-_max(l1,l2)+1;
    66         else{
    67             if(h1>h2)h1^=h2^=h1^=h2;
    68             b=neg.RMQ(h1+1,h2);if((b>r1-l1+1)||(b>r2-l2+1))b=_min(r1-l1+1,r2-l2+1);
    69         }//get b.
    70         printf("%lld
    ",1ll*a*a+1ll*b*b);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    Python进阶之浅谈内置方法(补充)
    Python进阶之浅谈内置方法
    Python运算符优先级
    python之浅谈循环
    MTCNN
    MTCNN
    tf.train.batch and tf.train.shuffle_batch
    tf.add_to_collection 和 tf.get_collection 和 tf.add_n
    tensorflow 迁移学习-Demo
    tensorflow 加载预训练模型进行 finetune 的操作解析
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10344542.html
Copyright © 2020-2023  润新知