zoukankan      html  css  js  c++  java
  • BZOJ3796 : Mushroom追妹纸

    将S1与S2用#号拼接在一起形成S串

    将S3与S串跑KMP求出S3在S串中每次出现的位置l[i]

    对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀

    然后求出S串的后缀数组

    先从小到大扫描后缀数组,

    同时维护一个tmp表示S2中的串与现在的串的最长公共前缀,且没有出现S3,

    如果碰到一个S1的后缀,那么更新ans=max(ans,min(f[sa[i]],tmp))

    如果碰到一个S2的后缀,那么更新tmp=max(tmp,f[sa[i]])

    然后将tmp与height取一个最小值

    最后再从后往前扫描一次即可

    时间复杂度$O(n)$

    #include<cstdio>
    #include<cstring>
    using std::strlen;
    inline bool leq(int a1,int a2,int b1,int b2){return a1<b1||a1==b1&&a2<=b2;}
    inline bool leq(int a1,int a2,int a3,int b1,int b2,int b3){return a1<b1||a1==b1&&leq(a2,a3,b2,b3);}
    inline void radixPass(int*a,int*b,int*r,int n,int K){
      int*c=new int[K+1];
      int i,sum,t;
      for(i=0;i<=K;i++)c[i]=0;
      for(i=0;i<n;i++)c[r[a[i]]]++;
      for(i=sum=0;i<=K;i++)t=c[i],c[i]=sum,sum+=t;
      for(i=0;i<n;i++)b[c[r[a[i]]]++]=a[i];
      delete[]c;
    }
    void suffixArray(int*T,int*SA,int n,int K){
      int n0=(n+2)/3,n1=(n+1)/3,n2=n/3,n02=n0+n2;
      int*R=new int[n02+3];R[n02]=R[n02+1]=R[n02+2]=0;
      int*SA12=new int[n02+3];SA12[n02]=SA12[n02+1]=SA12[n02+2]=0;
      int*R0=new int[n0];
      int*SA0=new int[n0];
      int i,j,name=0,c0=-1,c1=-1,c2=-1,p=0,t=n0-n1,k=0;
      for(i=j=0;i<n+n0-n1;i++)if(i%3)R[j++]=i;
      radixPass(R,SA12,T+2,n02,K),radixPass(SA12,R,T+1,n02,K),radixPass(R,SA12,T,n02,K);
      for(i=0;i<n02;i++){
        if(T[SA12[i]]!=c0||T[SA12[i]+1]!=c1||T[SA12[i]+2]!=c2)name++,c0=T[SA12[i]],c1=T[SA12[i]+1],c2=T[SA12[i]+2];
        if(SA12[i]%3==1)R[SA12[i]/3]=name;else R[SA12[i]/3+n0]=name;
      }
      if(name<n02)for(suffixArray(R,SA12,n02,name),i=0;i<n02;i++)R[SA12[i]]=i+1;else for(i=0;i<n02;i++)SA12[R[i]-1]=i;
      for(i=j=0;i<n02;i++)if(SA12[i]<n0)R0[j++]=3*SA12[i];
      for(radixPass(R0,SA0,T,n0,K);k<n;k++){
        #define GetI() (SA12[t]<n0?SA12[t]*3+1:(SA12[t]-n0)*3+2)
        i=GetI(),j=SA0[p];
        if(SA12[t]<n0?leq(T[i],R[SA12[t]+n0],T[j],R[j/3]):leq(T[i],T[i+1],R[SA12[t]-n0+1],T[j],T[j+1],R[j/3+n0])){
          SA[k]=i;
          if(++t==n02)for(k++;p<n0;p++,k++)SA[k]=SA0[p];
        }else{
          SA[k]=j;
          if(++p==n0)for(k++;t<n02;t++,k++)SA[k]=GetI();
        }
      }
      delete[]R;delete[]SA12;delete[]SA0;delete[]R0;
    }
    #define N 100010
    char s1[N],s2[N],s3[N],s[N],ch;
    int l1,l2,l3,n,nxt[N],S[N],SA[N],rank[N],height[N],f[N],i,j,k,cnt,loc[N],ans,tmp;
    inline int min(int a,int b){return a<b?a:b;}
    inline void Min(int&a,int b){if(a>b)a=b;}
    inline void Max(int&a,int b){if(a<b)a=b;}
    int main(){
      scanf("%s%s%s",s1,s2,s3);
      l1=strlen(s1),l2=strlen(s2),l3=strlen(s3);
      for(i=0;i<l1;i++)s[i]=s1[i];
      for(s[n=l1]='#',i=0;i<l2;i++)s[++n]=s2[i];++n;
      for(nxt[0]=j=-1,i=1;i<l3;nxt[i++]=j){
        while(~j&&s3[j+1]!=s3[i])j=nxt[j];
        if(s3[j+1]==s3[i])j++;
      }
      for(j=-1,i=0;i<n;i++){
        while(~j&&s3[j+1]!=s[i])j=nxt[j];
        if(s3[j+1]==s[i])j++;
        if(j==l3-1)loc[++cnt]=i-l3+1,j=nxt[j];
      }
      for(i=0,j=1;i<n;i++){
        while(j<=cnt&&loc[j]<i)j++;
        if(j>cnt)f[i]=n-i;else f[i]=loc[j]+l3-i-1;
      }
      for(i=0;i<=l1;i++)Min(f[i],l1-i);
      for(i=0;i<n;i++)if(s[i]=='#')S[i]=27;else S[i]=s[i]-'a'+1;
      suffixArray(S,SA,n,27);
      for(i=0;i<n;i++)rank[SA[i]]=i;
      for(k=i=0;i<n;i++)if(rank[i]==n-1)k=0;
      else{
        if(k)k--;
        for(j=SA[rank[i]+1];S[i+k]==S[j+k];k++);
        height[rank[i]]=k;
      }
      for(i=tmp=0;i<n;i++){
        if(SA[i]<l1)Max(ans,min(tmp,f[SA[i]]));
        if(SA[i]>l1)Max(tmp,f[SA[i]]);
        Min(tmp,height[i]);
      }
      for(i=n-1,tmp=0;~i;i--){
        if(SA[i]<l1)Max(ans,min(tmp,f[SA[i]]));
        if(SA[i]>l1)Max(tmp,f[SA[i]]);
        if(i)Min(tmp,height[i-1]);
      }
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    蓝桥杯——一步之遥,扩展gcd的应用
    质数唯一分解定理应用——多个数的最小公约数和最大公倍数
    蓝桥杯训练 ——天平称重
    蓝桥杯 奇怪的捐赠——进制的运用
    Kubernetes-基本概念
    Docker-基本概念
    虚拟化向容器化发展
    Kubernetes-服务连接和暴露(endpoints资源)
    Kubernetes-NodePort
    Kubernetes-Load Balancer
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403187.html
Copyright © 2011-2022 走看看