• POJ 1225 Substrings


    http://poj.org/problem?id=1226

    题意:给定n个串。求一个最长的串,使得这个串或者其反串在每个串中都出现过?

    思路:先在大串里面加入正反串,然后二分,判定即可。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 int num[200005],ws[200005],wv[200005],wb[200005],wa[200005];
     7 int n,m,rank[200005],sa[200005],h[200005],b[200005];
     8 int read(){
     9     int t=0,f=1;char ch=getchar();
    10     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    12     return t*f;
    13 }
    14 bool cmp(int *r,int a,int b,int l){
    15     return r[a]==r[b]&&r[a+l]==r[b+l];
    16 }
    17 void da(int *r,int *sa,int n,int m){
    18     int *y=wb,*x=wa,*t,i,j,p;
    19     for (i=0;i<m;i++) ws[i]=0;
    20     for (i=0;i<n;i++) x[i]=r[i];
    21     for (i=0;i<n;i++) ws[x[i]]++;
    22     for (i=1;i<m;i++) ws[i]+=ws[i-1];
    23     for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
    24     for (p=1,j=1;p<n;m=p,j*=2){
    25         for (p=0,i=n-j;i<n;i++) y[p++]=i;
    26         for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
    27         for (i=0;i<m;i++) ws[i]=0;
    28         for (i=0;i<n;i++) wv[i]=x[y[i]];
    29         for (i=0;i<n;i++) ws[wv[i]]++;
    30         for (i=1;i<m;i++) ws[i]+=ws[i-1];
    31         for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
    32         for (t=x,x=y,y=t,i=1,p=1,x[sa[0]]=0;i<n;i++)
    33          x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
    34     }
    35 }
    36 void cal(int *r,int n){
    37     int i,j,k=0;
    38     for (i=1;i<=n;i++) rank[sa[i]]=i;
    39     for (i=0;i<n;h[rank[i++]]=k)
    40      for (k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    41 }
    42 bool check(int x){
    43     int L,R;
    44     int hash[105];
    45     for (int i=1;i<=n;i++){
    46         L=i;
    47         while (L<=n&&h[L]<x) L++;
    48         if (L>n) break;
    49         R=L;
    50         while (R<=n&&h[R]>=x) R++;
    51         memset(hash,0,sizeof hash);
    52         for (int j=L-1;j<=R-1;j++)
    53          if (b[sa[j]]<=m)
    54           hash[b[sa[j]]]=1;
    55         int j=0;
    56         for (j=1;j<=m;j++)
    57          if (!hash[j]) break;
    58         if (j>m) return 1; 
    59         i=R; 
    60     }
    61     return 0;
    62 }
    63 void solve(){
    64     int l=0,r=100,ans;
    65     while (l<=r){
    66         int mid=(l+r)>>1;
    67         if (check(mid)) ans=mid,l=mid+1;
    68         else r=mid-1;
    69     }
    70     printf("%d
    ",ans);
    71 }
    72 int main(){
    73     int T=read();
    74     char s[200005];
    75     while (T--){
    76         m=read();n=0;int sx=130;
    77         for (int i=1;i<=m;i++){
    78             scanf("%s",s);
    79             int len=strlen(s);
    80             for (int j=0;j<len;j++)
    81              num[n]=s[j],b[n++]=i;
    82             num[n]=sx++;b[n++]=n+1; 
    83             for (int j=len-1;j>=0;j--)
    84              num[n]=s[j],b[n++]=i;
    85             num[n]=sx++;b[n++]=n+1; 
    86         }
    87         num[n]=0;b[n]=n+1;
    88         da(num,sa,n+1,sx+10);
    89         cal(num,n);
    90         solve();
    91     }
    92 }
  • 相关阅读:
    第九次任务
    第八次任务
    第七次任务
    第六次任务
    第四天半任务
    第四天任务
    第三天任务
    第二天任务
    第一天任务
    第⑩天任务
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5638984.html
Copyright © 2020-2023  润新知