zoukankan      html  css  js  c++  java
  • poj 3294 Life Forms 后缀数组

    题意:给n个字符串,求一个最长的子串至少出现在[n/2+1]个字符串中

    思路:后缀数组 把所有字串连一起,并用不同的字符隔开 二分

    P.S. 1. 我的程序C++WA,G++ AC

       2. 为什么char的上界是127啊

      1 #include<iostream>
    2 #include<cstring>
    3 #include<cstdio>
    4 using namespace std;
    5 #define MAXN 110000
    6 int n,m;
    7 int suffix_array[MAXN];
    8 int rank[2*MAXN],oldrank[2*MAXN];
    9 int cnt[MAXN],tmp[MAXN];
    10 int height[MAXN];
    11 int a[MAXN];
    12 int mark[MAXN];
    13 void SuffixArray()
    14 {
    15 int memo[300];
    16 suffix_array[0]=0;
    17 memset(memo,0,sizeof(memo));
    18 memset(rank,0,sizeof(rank));
    19 memset(oldrank,0,sizeof(oldrank));
    20 int i,l;
    21 for(i=1;i<=n;i++) memo[a[i]]=1;
    22 for(i=1;i<300;i++) memo[i]+=memo[i-1];
    23 for(i=1;i<=n;i++) rank[i]=memo[a[i]];
    24 for(l=1;l<=n;l*=2)
    25 {
    26 memset(cnt,0,sizeof(cnt));
    27 for(i=1;i<=n;i++) cnt[rank[i+l]]++;
    28 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1];
    29 for(i=1;i<=n;i++) tmp[cnt[rank[i+l]]--]=i;
    30
    31 memset(cnt,0,sizeof(cnt));
    32 for(i=1;i<=n;i++) cnt[rank[tmp[i]]]++;
    33 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1];
    34 for(i=n;i>0;i--) suffix_array[cnt[rank[tmp[i]]]--]=tmp[i];
    35
    36 memcpy(oldrank,rank,sizeof(rank));
    37 rank[suffix_array[1]]=1;
    38 int k=1;
    39 for(i=2;i<=n;i++)
    40 {
    41 int x=suffix_array[i-1],y=suffix_array[i];
    42 if(oldrank[x]!=oldrank[y]||oldrank[x+l]!=oldrank[y+l]) k++;
    43 rank[y]=k;
    44 }
    45 if(k==n) break;
    46 }
    47 }
    48 void LCP()
    49 {
    50 int i,j,k=0;
    51 for(i=1;i<=n;i++)
    52 {
    53 if(rank[i]==n)
    54 {
    55 height[n]=k=0; continue;
    56 }
    57 j=suffix_array[rank[i]+1];
    58 k=max(k-1,0);
    59 while(a[j+k]==a[i+k]) k++;
    60 height[rank[i]]=k;
    61 }
    62 height[0]=-1; mark[0]=m+1;
    63 }
    64 bool check(int mid,bool w)
    65 {
    66 bool use[102];
    67 memset(use,0,sizeof(use));
    68 int k=1;
    69 int i,j;
    70 for(i=1;i<=n;i++)
    71 {
    72 if(a[suffix_array[i-1]]>'z') break;
    73 if(height[i-1]>=mid)
    74 {
    75 if(use[mark[suffix_array[i]]]==0)
    76 {
    77 use[mark[suffix_array[i]]]=1;
    78 k++;
    79 }
    80 }
    81 else
    82 {
    83 if(k>m/2)
    84 {
    85 if(w==0) return 1;
    86 for(j=suffix_array[i-1];j<=suffix_array[i-1]+mid-1;j++)
    87 printf("%c",a[j]);
    88 printf("\n");
    89 }
    90 memset(use,0,sizeof(use));
    91 k=1; use[mark[suffix_array[i]]]=1;
    92 }
    93
    94 }
    95 if(w==0)
    96 return 0;
    97 printf("\n");
    98 }
    99 int binary()
    100 {
    101 int left=0,right=n+1;
    102 int mid;
    103 while(left<right)
    104 {
    105 mid=(left+right)/2;
    106 if(check(mid,0)) left=mid;
    107 else right=mid;
    108 if(right-left==1) return left;
    109 }
    110 }
    111 int main()
    112 {
    113 char c[1001];
    114 scanf("%d",&m);
    115 int i,j,l,k;
    116 int maxl;
    117 while(m!=0)
    118 {
    119 memset(a,0,sizeof(a));
    120 j=1;
    121 for(i=1;i<=m;i++)
    122 {
    123 scanf("%s",c);
    124 l=strlen(c);
    125 for(k=j;k<=l+j-1;k++)
    126 {
    127 mark[k]=i;
    128 a[k]=c[k-j];
    129 }
    130 j=j+l; mark[j]=m+1; a[j]='z'+i;
    131 j++;
    132 }
    133 if(m==1)
    134 {
    135 printf("%s\n\n",c);
    136 scanf("%d",&m);
    137 continue;
    138 }
    139 n=j-2;
    140 SuffixArray();
    141 LCP();
    142 maxl=binary();
    143 if(maxl!=0) check(maxl,1);
    144 else printf("?\n\n");
    145 scanf("%d",&m);
    146 }
    147 return 0;
    148 }
    149
    150
    151


    答案

  • 相关阅读:
    java编码过滤器
    DAO设计模式
    常用的SQL语句
    IO流总结
    IO流的登录与注册
    设计模式之模板方法模式(Template Method)详解及代码示例
    设计模式之享元模式(Flyweight)详解及代码示例
    设计模式之桥接模式(Bridge)详解及代码示例
    设计模式之组合模式(Composite)详解及代码示例
    设计模式之外观模式(Facade)详解及代码示例
  • 原文地址:https://www.cnblogs.com/myoi/p/2343835.html
Copyright © 2011-2022 走看看