• POJ1226 Substrings


    后缀数组。

    求多个字符串翻转与否中最长公共子串长。

    二分答案,反过来多建一倍的字符串,二分时特判一下即可。

    By:大奕哥

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<iostream>
     6 #define rank fank
     7 using namespace std;
     8 const int N=1000005;
     9 int r[N],wa[N],wb[N],wv[N],wu[N],sa[N],rank[N],height[N],bel[N],cnt;
    10 int cmp(int *r,int a,int b,int l)
    11 {
    12     return r[a]==r[b]&&r[a+l]==r[b+l];
    13 }
    14 void da(int *r,int *sa,int n,int m)
    15 {
    16     int i,j,p;int *x=wa,*y=wb;
    17     for(i=0;i<m;++i)wu[i]=0;
    18     for(i=0;i<n;++i)wu[x[i]=r[i]]++;
    19     for(i=1;i<m;++i)wu[i]+=wu[i-1];
    20     for(i=n-1;i>=0;--i)sa[--wu[x[i]]]=i;
    21     for(j=1,p=1;p<n;j<<=1,m=p)
    22     {
    23         for(p=0,i=n-j;i<n;++i)y[p++]=i;
    24         for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
    25         for(i=0;i<n;++i)wv[i]=x[y[i]];
    26         for(i=0;i<m;++i)wu[i]=0;
    27         for(i=0;i<n;++i)wu[wv[i]]++;
    28         for(i=0;i<m;++i)wu[i]+=wu[i-1];
    29         for(i=n-1;i>=0;--i)sa[--wu[wv[i]]]=y[i];
    30         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;++i)
    31         x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    32     }
    33     return;
    34 }
    35 void calcHeight(int *rank,int *sa,int n)
    36 {
    37     int i,j,k=0;
    38     for(i=1;i<=n;++i)rank[sa[i]]=i;
    39     for(i=0;i<n;height[rank[i++]]=k)
    40         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];++k);
    41     return ;
    42 }
    43 char s[1005];
    44 bool v[1005];
    45 int tot,num;
    46 bool check(int x,int n)
    47 {
    48     cnt=0;memset(v,0,sizeof(v));
    49     for(int i=1;i<=n;++i)
    50     {
    51         if(height[i]<x){cnt=0;memset(v,0,sizeof(v));}
    52         else
    53         {
    54             if(v[bel[sa[i-1]]]==0)cnt++,v[bel[sa[i-1]]]=1;
    55             if(!v[bel[sa[i]]])cnt++,v[bel[sa[i]]]=1;
    56             if(cnt>=num)return 1;
    57         }
    58     }
    59     return 0;
    60 }
    61 int main()
    62 {
    63     int t;
    64     scanf("%d",&t);
    65     while(t--)
    66     {
    67     scanf("%d",&num);
    68     int len=0;int p=0;
    69     for(int i=0;i<num;++i)
    70     {
    71         scanf("%s",s);
    72         int n=strlen(s);
    73         for(int j=0;j<n;++j)
    74         {
    75             r[len]=s[j];bel[len]=i;++len;
    76         } 
    77         r[len]=200+p;bel[len]=200+p;++len;++p;
    78         for(int j=n-1;j>=0;--j)
    79         {
    80             r[len]=s[j];bel[len]=i;++len;
    81         }
    82         r[len]=200+p;bel[len]=200+p;++len;++p;
    83     }
    84     --len;r[len]=0;
    85     da(r,sa,len+1,1000);
    86     calcHeight(rank,sa,len);
    87     int ans=0,l=1,r=len;
    88     while(l<=r)
    89     {
    90         int mid=l+r>>1;
    91         if(check(mid,len))ans=mid,l=mid+1;
    92         else r=mid-1;
    93     }
    94     printf("%d
    ",ans);
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    Codeforces 1265A Beautiful String
    1039 Course List for Student (25)
    1038 Recover the Smallest Number (30)
    1037 Magic Coupon (25)
    1024 Palindromic Number (25)
    1051 Pop Sequence (25)
    1019 General Palindromic Number (20)
    1031 Hello World for U (20)
    1012 The Best Rank (25)
    1011 World Cup Betting (20)
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8206490.html
Copyright © 2020-2023  润新知