zoukankan      html  css  js  c++  java
  • POJ1226 Substrings(二分+后缀数组)

    题意:给n个字符串,求最长的子串,满足它或它的逆置出现在所有的n个字符串中。

    • 把n个字符串及其它们的逆置拼接,中间用不同字符隔开,并记录suffix(i)是属于哪个字符串的;
    • 跑后缀数组计算height;
    • 二分答案,height分组,看组里面是否都包含了n个字符串的后缀;
    • 注意n=1的情况。。
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 using namespace std;
      6 #define MAXN 22222 
      7 int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
      8 int cmp(int *r,int a,int b,int l){
      9     return r[a]==r[b] && r[a+l]==r[b+l];
     10 }
     11 int sa[MAXN],rank[MAXN],height[MAXN];
     12 void SA(int *r,int n,int m){
     13     int *x=wa,*y=wb;
     14 
     15     for(int i=0; i<m; ++i) ws[i]=0;
     16     for(int i=0; i<n; ++i) ++ws[x[i]=r[i]];
     17     for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
     18     for(int i=n-1; i>=0; --i) sa[--ws[x[i]]]=i;
     19 
     20     int p=1;
     21     for(int j=1; p<n; j<<=1,m=p){
     22         p=0;
     23         for(int i=n-j; i<n; ++i) y[p++]=i;
     24         for(int i=0; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
     25         for(int i=0; i<n; ++i) wv[i]=x[y[i]];
     26         for(int i=0; i<m; ++i) ws[i]=0;
     27         for(int i=0; i<n; ++i) ++ws[wv[i]];
     28         for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
     29         for(int i=n-1; i>=0; --i) sa[--ws[wv[i]]]=y[i];
     30         swap(x,y); x[sa[0]]=0; p=1;
     31         for(int i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     32     }
     33 
     34     for(int i=1; i<n; ++i) rank[sa[i]]=i;
     35     int k=0;
     36     for(int i=0; i<n-1; height[rank[i++]]=k){
     37         if(k) --k;
     38         for(int j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k);
     39     }
     40 }
     41 
     42 int sn,n,r[MAXN],belong[MAXN];
     43 bool isok(int len){
     44     bool vis[111]={0}; int cnt=0;
     45     for(int i=2; i<=n; ++i){
     46         if(height[i]>=len){
     47             if(!vis[belong[sa[i]]]){
     48                 vis[belong[sa[i]]]=1;
     49                 ++cnt;
     50             }
     51             if(!vis[belong[sa[i-1]]]){
     52                 vis[belong[sa[i-1]]]=1;
     53                 ++cnt;
     54             }
     55             if(cnt==sn) return 1;
     56         }else{
     57             if(cnt==sn) return 1;
     58             memset(vis,0,sizeof(vis));
     59             cnt=0;
     60         }
     61     }
     62     return 0;
     63 }
     64 int main(){
     65     char str[111];
     66     int t;
     67     scanf("%d",&t);
     68     while(t--){
     69         n=0;
     70         scanf("%d",&sn);
     71         for(int i=0; i<sn; ++i){
     72             scanf("%s",str);
     73             if(sn==1){
     74                 printf("%d
    ",strlen(str));
     75                 break;
     76             }
     77             for(int j=0; str[j]; ++j){
     78                 belong[n]=i;
     79                 r[n++]=str[j];
     80             }
     81             r[n++]=127+(i<<1);
     82             for(int j=strlen(str)-1; j>=0; --j){
     83                 belong[n]=i;
     84                 r[n++]=str[j];
     85             }
     86             r[n++]=127+(i<<1|1);
     87         }
     88         if(sn==1) continue;
     89         r[--n]=0;
     90         SA(r,n+1,333);
     91         int l=0,r=100;
     92         while(l<r){
     93             int mid=l+r+1>>1;
     94             if(isok(mid)) l=mid;
     95             else r=mid-1;
     96         }
     97         printf("%d
    ",l);
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    23、Django实战第23天:视频播放页面
    22、Django实战第22天:课程评论
    21、Django实战第21天:课程章节信息
    20、Django实战第20天:课程详情页
    19、Django实战第19天:课程列表页
    Tomcat 的 catalina.out 日志分割
    18、Django实战第18天:课程机构收藏功能
    17、Django实战第17天:机构详情展示
    16、Django实战第16天:优化url
    15、Django实战第15天:我要学习咨询
  • 原文地址:https://www.cnblogs.com/WABoss/p/5225007.html
Copyright © 2011-2022 走看看