zoukankan      html  css  js  c++  java
  • [poj3450]Corporate Identity(后缀数组)

    题意:多个字符串的最长公共子串。

    解题关键:字符串的任何一个子串都是这个字符串的某个后缀的前缀。求A和B的最长公共子串等价于求A的后缀和B的后缀的最长公共前缀的最大值。

    后缀数组的经典例题,连接在一起,二分长度,height数组遍历即可。

    注意flag的问题,采用二分小于的方式,可能会出现有最优解但是flag为false的情况,下界需要-1,采用0,而采用等于的话,就不会出现,不过有些题会出现死循环。

    还有因为多添加的符号一定不会加入vis数组,所以vis数组只需建立4000即可。

    为什么两个字符串不需要二分?而多个字符串需要二分?因为 两个字符串可以直接判定height[i]是属于两个字符串的最大公共子串,而多个必须通过vis数组判定。

    法一:

     1 #include<cstdlib>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<cmath>
     7 using namespace std;
     8 const int N=800005;
     9 int r[N],id[N];
    10 char tmp[220],ans[220];
    11 bool vis[4200];
    12 
    13 int wa[N],wb[N],wv[N],wc[N],n,m;
    14 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
    15 void make_sa(int *r,int *sa,int n,int m){
    16     int i,j,p,*x=wa,*y=wb;
    17     for(i=0;i<m;i++) wc[i]=0;
    18     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
    19     for(i=1;i<m;i++) wc[i]+=wc[i-1];
    20     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
    21     for(j=1,p=1;p<n;j*=2,m=p){
    22         for(p=0,i=n-j;i<n;i++) y[p++]=i;
    23         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    24         for(i=0;i<n;i++) wv[i]=x[y[i]];
    25         for(i=0;i<m;i++) wc[i]=0;
    26         for(i=0;i<n;i++) wc[wv[i]]++;
    27         for(i=1;i<m;i++) wc[i]+=wc[i-1];
    28         for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i];
    29         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    30     }
    31     return;
    32 }
    33 int rank1[N],height[N],sa[N];
    34 void make_height(int *r,int *sa,int n){
    35     int i,j,k=0;
    36     for(i=1;i<=n;i++) rank1[sa[i]]=i;
    37     for(i=0;i<n;height[rank1[i++]]=k)
    38         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
    39     return;
    40 }
    41 
    42 bool check(int x){
    43     memset(vis,0,sizeof vis);
    44     int cnt=0;
    45     for(int i=2;i<=n;i++){
    46         if(height[i]<x){
    47             memset(vis,0,sizeof vis);
    48             cnt=0;
    49             continue;
    50         }
    51         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
    52         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
    53         if(cnt==m){
    54             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
    55             return true;
    56         }
    57     }
    58     return false;
    59 }
    60 
    61 bool erfen(int l,int r){
    62     bool flag=false;
    63     while(l<r){
    64         int mid=(l+r+1)>>1;
    65         if(check(mid)) l=mid,flag=true;
    66         else r=mid-1;
    67     }
    68     return flag;
    69 }
    70 
    71 int main() {
    72     while(scanf("%d",&m)&&m){
    73         n=0;
    74         int temp=30;
    75         for(int i=1;i<=m;i++){
    76             scanf("%s",tmp);
    77             int siz=strlen(tmp);
    78             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
    79             id[n]=temp;
    80             r[n++]=temp++;
    81         }
    82         r[n]=0;
    83         make_sa(r,sa,n+1,4001);
    84         make_height(r,sa,n);
    85         bool f=erfen(0,200);//为什么0可以,1不可以 
    86         if(f) printf("%s
    ",ans);
    87         else printf("IDENTITY LOST
    ");
    88     }
    89 }

    法二:

     1 #include<cstdlib>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<cmath>
     7 using namespace std;
     8 const int N=800005;
     9 int r[N],id[N];
    10 char tmp[220],ans[220];
    11 bool vis[4200];
    12 
    13 int wa[N],wb[N],wv[N],wc[N],n,m;
    14 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
    15 void make_sa(int *r,int *sa,int n,int m){
    16     int i,j,p,*x=wa,*y=wb;
    17     for(i=0;i<m;i++) wc[i]=0;
    18     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
    19     for(i=1;i<m;i++) wc[i]+=wc[i-1];
    20     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
    21     for(j=1,p=1;p<n;j*=2,m=p){
    22         for(p=0,i=n-j;i<n;i++) y[p++]=i;
    23         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    24         for(i=0;i<n;i++) wv[i]=x[y[i]];
    25         for(i=0;i<m;i++) wc[i]=0;
    26         for(i=0;i<n;i++) wc[wv[i]]++;
    27         for(i=1;i<m;i++) wc[i]+=wc[i-1];
    28         for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i];
    29         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    30     }
    31     return;
    32 }
    33 int rank1[N],height[N],sa[N];
    34 void make_height(int *r,int *sa,int n){
    35     int i,j,k=0;
    36     for(i=1;i<=n;i++) rank1[sa[i]]=i;
    37     for(i=0;i<n;height[rank1[i++]]=k)
    38         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
    39     return;
    40 }
    41 
    42 bool check(int x){
    43     memset(vis,0,sizeof vis);
    44     int cnt=0;
    45     for(int i=2;i<=n;i++){
    46         if(height[i]<x){
    47             memset(vis,0,sizeof vis);
    48             cnt=0;
    49             continue;
    50         }
    51         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
    52         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
    53         if(cnt==m){
    54             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
    55             return true;
    56         }
    57     }
    58     return false;
    59 }
    60 
    61 bool erfen(int l,int r){
    62     bool flag=false;
    63     while(l<=r){
    64         int mid=(l+r+1)>>1;
    65         if(check(mid)) l=mid+1,flag=true;
    66         else r=mid-1;
    67     }
    68     return flag;
    69 }
    70 
    71 int main() {
    72     while(scanf("%d",&m)&&m){
    73         n=0;
    74         int temp=30;
    75         for(int i=1;i<=m;i++){
    76             scanf("%s",tmp);
    77             int siz=strlen(tmp);
    78             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
    79             id[n]=temp;
    80             r[n++]=temp++;
    81         }
    82         r[n]=0;
    83         make_sa(r,sa,n+1,4001);
    84         make_height(r,sa,n);
    85         bool f=erfen(1,200);//为什么0可以,1不可以 
    86         if(f) printf("%s
    ",ans);
    87         else printf("IDENTITY LOST
    ");
    88     }
    89 }

    dc3:依然注意是3倍的问题

      1 #include<cstdlib>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<cmath>
      7 #define inf 0x3f3f3f3f
      8 typedef long long ll;
      9 using namespace std;
     10 const int N=800005;
     11 #define F(x) ((x)/3+((x)%3==1?0:tb))
     12 #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
     13 int wa[N],wb[N],wv[N],ws1[N];
     14 int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2]; }
     15 int c12(int k,int *r,int a,int b){ 
     16     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
     17     else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
     18 }
     19 void sort(int *r,int *a,int *b,int n,int m){
     20     int i;
     21     for(i=0;i<n;i++) wv[i]=r[a[i]];
     22     for(i=0;i<m;i++) ws1[i]=0;
     23     for(i=0;i<n;i++) ws1[wv[i]]++;
     24     for(i=1;i<m;i++) ws1[i]+=ws1[i-1];
     25     for(i=n-1;i>=0;i--) b[--ws1[wv[i]]]=a[i];
     26     return;
     27 }
     28 void dc3(int *r,int *sa,int n,int m){
     29     int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
     30     r[n]=r[n+1]=0;
     31     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
     32     sort(r+2,wa,wb,tbc,m);
     33     sort(r+1,wb,wa,tbc,m);
     34     sort(r,wa,wb,tbc,m);
     35     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
     36     rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
     37     if(p<tbc) dc3(rn,san,tbc,p);
     38     else for(i=0;i<tbc;i++) san[rn[i]]=i;
     39     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
     40     if(n%3==1) wb[ta++]=n-1;
     41     sort(r,wb,wa,ta,m);
     42     for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
     43     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
     44     sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
     45     for(;i<ta;p++) sa[p]=wa[i++];
     46     for(;j<tbc;p++) sa[p]=wb[j++];
     47     return;
     48 }
     49 int rank1[N],height[N],sa[3*N];
     50 void make_height(int *r,int *sa,int n){
     51     int i,j,k=0;
     52     for(i=1;i<=n;i++) rank1[sa[i]]=i;
     53     for(i=0;i<n;height[rank1[i++]]=k)
     54         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
     55     return;
     56 }
     57 int r[3*N],id[N],n,m;
     58 char tmp[220],ans[220];
     59 bool vis[4200];
     60 
     61 bool check(int x){
     62     memset(vis,0,sizeof vis);
     63     int cnt=0;
     64     for(int i=2;i<=n;i++){
     65         if(height[i]<x){
     66             memset(vis,0,sizeof vis);
     67             cnt=0;
     68             continue;
     69         }
     70         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
     71         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
     72         if(cnt==m){
     73             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
     74             return true;
     75         }
     76     }
     77     return false;
     78 }
     79 
     80 bool erfen(int l,int r){
     81     bool flag=false;
     82     while(l<r){
     83         int mid=(l+r+1)>>1;
     84         if(check(mid)) l=mid,flag=true;
     85         else r=mid-1;
     86     }
     87     return flag;
     88 }
     89 
     90 int main() {
     91     while(scanf("%d",&m)&&m){
     92         n=0;
     93         int temp=30;
     94         for(int i=1;i<=m;i++){
     95             scanf("%s",tmp);
     96             int siz=strlen(tmp);
     97             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
     98             id[n]=temp;
     99             r[n++]=temp++;
    100         }
    101         r[n]=0;
    102         dc3(r,sa,n+1,4001);
    103         make_height(r,sa,n);
    104         bool f=erfen(0,200);//为什么0可以,1不可以 
    105         if(f) printf("%s
    ",ans);
    106         else printf("IDENTITY LOST
    ");
    107     }
    108 }
  • 相关阅读:
    cgic: CGI的C函数库
    linux下的webserver BOA及CGIC库的使用指南(转帖)
    UDP 收/发 广播包
    winsock 收发广播包
    Linux系统下UDP发送和接收广播消息小例子
    uboot里读sd卡内容
    uboot从SD卡烧写内核和文件系统
    intellij 创建一个文件自动就add到git了,这个怎么取消
    内部类和外部类之间的相互调用
    JDK8的新特性——Lambda表达式
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7575725.html
Copyright © 2011-2022 走看看