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

      题目链接:http://poj.org/problem?id=3294

      多个串中,出现次数为k次的最长公共子串的个数,并且输出。

      一般的算法就是后缀数组加二分,复杂度O(n*logn)。其实也可以和POJ3415一样维护一个栈,思想都是差不多的,维护一个单调递增的栈,每到一个height[i]时,先保证栈单调递增并且统计个数sum,然后height[i]再与当前最优值比较,如果大于最优值,那么看sum是否大于k,如果大于则更新最优值。平均复杂度O(n)。

      二分代码:

      1 //STATUS:C++_AC_375MS_4328KB
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<math.h>
      6 #include<iostream>
      7 #include<string>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<stack>
     12 #include<map>
     13 using namespace std;
     14 #define LL long long
     15 #define pii pair<int,int>
     16 #define Max(a,b) ((a)>(b)?(a):(b))
     17 #define Min(a,b) ((a)<(b)?(a):(b))
     18 #define mem(a,b) memset(a,b,sizeof(a))
     19 #define lson l,mid,rt<<1
     20 #define rson mid+1,r,rt<<1|1
     21 #define PI acos(-1.0)
     22 const int N=101010,INF=0x3f3f3f3f,MOD=10000,STA=8000010;
     23 const LL LNF=0x3f3f3f3f3f3f3f3f;
     24 const double DNF=1e13;
     25 //
     26 void swap(int& a,int& b){int t=a;a=b;b=t;}
     27 void swap(LL& a,LL& b){LL t=a;a=b;b=t;}
     28 //
     29 
     30 int num[N];
     31 int sa[N],t1[N],t2[N],c[N],rank[N],height[N],vis[N],ma[N];
     32 int n,m,T;
     33 
     34 void build_sa(int s[],int n,int m)
     35 {
     36     int i,k,p,*x=t1,*y=t2;
     37     //第一轮基数排序
     38     for(i=0;i<m;i++)c[i]=0;
     39     for(i=0;i<n;i++)c[x[i]=s[i]]++;
     40     for(i=1;i<m;i++)c[i]+=c[i-1];
     41     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
     42     for(k=1;k<=n;k<<=1){
     43         p=0;
     44         //直接利用sa数组排序第二关键字
     45         for(i=n-k;i<n;i++)y[p++]=i;
     46         for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
     47         //基数排序第一关键字
     48         for(i=0;i<m;i++)c[i]=0;
     49         for(i=0;i<n;i++)c[x[y[i]]]++;
     50         for(i=1;i<m;i++)c[i]+=c[i-1];
     51         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
     52         //根据sa和x数组计算新的x数组
     53         swap(x,y);
     54         p=1;x[sa[0]]=0;
     55         for(i=1;i<n;i++)
     56             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
     57         if(p>=n)break;   //已经排好序,直接退出
     58         m=p;     //下次基数排序的最大值
     59     }
     60 }
     61 
     62 void getHeight(int s[],int n)
     63 {
     64     int i,j,k=0;
     65     for(i=0;i<=n;i++)rank[sa[i]]=i;
     66     for(i=0;i<n;i++){
     67         if(k)k--;
     68         j=sa[rank[i]-1];
     69         while(s[i+k]==s[j+k])k++;
     70         height[rank[i]]=k;
     71     }
     72 }
     73 
     74 int binary(int l,int r)
     75 {
     76     int i,j,mid,ok,ret,k,cnt;
     77     mem(vis,0);k=1;
     78     while(l<=r){
     79         mid=(l+r)>>1;
     80         cnt=1;ok=0;
     81         vis[ma[sa[1]]]=k;
     82         for(i=2;i<=n;i++){
     83             if(height[i]>=mid){
     84                 if(vis[ma[sa[i]]]!=k)vis[ma[sa[i]]]=k,cnt++;
     85             }
     86             else {
     87                 if(cnt>T/2){ok=1;break;}
     88                 k++;cnt=1;
     89                 vis[ma[sa[i]]]=k;
     90             }
     91         }
     92         k++;
     93         if(cnt>T/2)ok=1;
     94         if(ok)ret=mid,l=mid+1;
     95         else r=mid-1;
     96     }
     97     return ret;
     98 }
     99 
    100 int main()
    101 {
    102  //   freopen("in.txt","r",stdin);
    103     int i,j,cnt,ans,k,t;
    104     char s[N];
    105     while(~scanf("%d",&T) && T)
    106     {
    107         n=0;cnt=130;
    108         for(i=0;i<T;i++){
    109             scanf("%s",s);
    110             for(j=0;s[j];j++){
    111                 ma[n]=i;
    112                 num[n++]=s[j]-'a'+1;
    113             }
    114             ma[n]=i;
    115             num[n++]=cnt++;
    116         }
    117         num[n]=0;
    118         m=cnt;
    119         build_sa(num,n+1,m);
    120         getHeight(num,n);
    121 
    122         ans=binary(0,1001);
    123         if(ans){
    124             if(T==1){
    125                 printf("%s\n\n",s);
    126                 continue;
    127             }
    128             mem(vis,0);
    129             k=1;cnt=1;
    130             vis[ma[sa[1]]]=1;
    131             for(i=2;i<=n;i++){
    132                 if(height[i]>=ans){
    133                     if(vis[ma[sa[i]]]!=k)vis[ma[sa[i]]]=k,cnt++;
    134                 }
    135                 else {
    136                     if(cnt>T/2){
    137                         for(j=sa[i-1],t=ans;t--;j++)
    138                             printf("%c",num[j]+'a'-1);
    139                         putchar('\n');
    140                     }
    141                     k++;cnt=1;
    142                     vis[ma[sa[i]]]=k;
    143                 }
    144             }
    145             if(cnt>T/2){
    146                 for(j=sa[i-1],t=ans;t--;j++)
    147                     printf("%c",num[j]+'a'-1);
    148                 putchar('\n');
    149             }
    150         }
    151         else printf("?\n");
    152         putchar('\n');
    153     }
    154     return 0;
    155 }
  • 相关阅读:
    UVa10779
    UVa10779
    C++ 内存管理学习笔记
    c++ 学习笔记
    AcWing 275 传纸条
    I
    Tree HDU6228
    Lpl and Energy-saving Lamps
    C
    Secret Poems
  • 原文地址:https://www.cnblogs.com/zhsl/p/3043848.html
Copyright © 2011-2022 走看看