• bzoj3976


    题解:

    先跑一下Sa

    然后再用kmp匹配一下哪一些位置不行

    然后二分答案

    代码:

    #include<bits/stdc++.h>
    const int N=100003;
    using namespace std;
    int t[N],a[N],xx[N],yy[N],*x,*y,height[N],rank[N],sa[N];
    int n,m,len,len1,pd[N],pd1[N],pd2[N],v[N],p,st[20][N],L[N];
    char s1[N],s2[N],s3[N];
    void get_fail()
    {
        t[0]=-1; int j;
        for (int i=0;i<len1;i++)
         {
            j=t[i];
            while (j!=-1&&s3[j]!=s3[i]) j=t[j];
            t[i+1]=++j;
         }
    }
    void kmp(char s[N],int a[N],int l)
    {
        int i=0; int j=0;
        while (j<=l)
         {
            if (s3[i]==s[j]||i==-1) i++,j++;
            else i=t[i];
            if (i==len1)
             {
                a[j-len1]=1;
                i=t[i];
             }
         }
    }
    int cmp(int i,int j,int k)
    {
        return y[i]==y[j]&&(i+k>len?-1:y[i+k])==(j+k>len?-1:y[j+k]);
    }
    void get_sa()
    {
        x=xx; y=yy; int m1=30;
        for (int i=1;i<=len;i++) v[x[i]=a[i]]++;
        for (int i=1;i<=m1;i++) v[i]+=v[i-1];
        for (int i=len;i>=1;i--) sa[v[x[i]]--]=i;
        for (int k=1;k<=len;k<<=1)
         {
            p=0;
            for (int i=len-k+1;i<=len;i++) y[++p]=i; 
            for (int i=1;i<=len;i++)
             if (sa[i]>k) y[++p]=sa[i]-k;
            for (int i=1;i<=m1;i++) v[i]=0;
            for (int i=1;i<=len;i++) v[x[y[i]]]++;
            for (int i=1;i<=m1;i++) v[i]+=v[i-1];
            for (int i=len;i>=1;i--) sa[v[x[y[i]]]--]=y[i];
            swap(x,y); p=2; x[sa[1]]=1;
            for (int i=2;i<=len;i++)
             x[sa[i]]=cmp(sa[i],sa[i-1],k)?p-1:p++;
            if (p>len) break;
            m1=p+1;
         }
        for (int i=1;i<=len;i++) rank[sa[i]]=i;
        p=0;
        for (int i=1;i<=len;i++)
         {
            if (rank[i]==1) continue;
            int j=sa[rank[i]-1];
            while (i+p<=len&&j+p<=len&&a[i+p]==a[j+p]) p++;
            height[rank[i]]=p;
            p=max(0,p-1);
         }
    }
    int calc(int x,int y)
    {
        int k=L[y-x]; 
        return max(st[k][x],st[k][y-(1<<k)+1]);
    }
    int divide(int l,int r)
    {
        int t=l,ans=r+1;
        while (l<=r)
         {
            int mid=(l+r)/2;
            if (calc(t,mid)) ans=min(ans,mid),r=mid-1;
            else l=mid+1;
         } 
        return ans;
    }
    int main()
    {
        scanf("%s",s1);
        n=strlen(s1);
        scanf("%s",s2);
        m=strlen(s2);
        scanf("%s",s3);
        len1=strlen(s3);
        get_fail();
        kmp(s1,pd1,n);
        kmp(s2,pd2,m);
        for (int i=1;i<=n;i++)a[i]=s1[i-1]-'a'+1,pd[i]=pd1[i-1];
        a[n+1]=0;len=n+1;
        for (int i=1;i<=m;i++)a[++len]=s2[i-1]-'a'+1,pd[len]=pd2[i-1];
        get_sa();
        for (int i=1;i<=len;i++)st[0][i]=pd[i];
        for (int i=1;i<=17;i++) 
         for (int j=1;j<=len;j++)
          if (j+(1<<i)-1<=len)st[i][j]=max(st[i-1][j],st[i-1][j+(1<<(i-1))]);
        int j=0;
        for (int i=1;i<=len;i++)
         {
            if (1<<(j+1)<=i) j++;
            L[i]=j;
         }
        int ans=0;
        for (int i=2;i<=len;i++)
         if (sa[i]<=n&&sa[i-1]>n+1||sa[i]>n+1&&sa[i-1]<=n)
          {
            int t=height[i];
            int pos=divide(sa[i],sa[i]+height[i]-len1);
            t=min(t,pos-sa[i]+1+len1-2);
            ans=max(ans,t);
          }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    vue2.0 微信分享
    小程序开发:canvas在画布上滑动,页面跟着滑动问题
    前端AES解密
    vue2上传图片到OSS
    vue给不同环境配置不同打包命令
    vue页面绑定数据,渲染页面时会出现页面闪烁
    解决微信浏览器无法使用window.location.reload刷新页面
    vue列表拖拽组件 vue-dragging
    千万别在Java类的static块里写会抛异常的代码!
    linux shell的一些配置
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8652973.html
Copyright © 2020-2023  润新知