zoukankan      html  css  js  c++  java
  • poj2774 Long Long Message(后缀数组)

     

    【题目链接】

     

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

     

    【题意】

     

      A & B的最长公共子序列。  

     

    【思路】

           拼接+height数组。将AB拼接成一个形如A$B的串,枚举height数组并判断sa[i]是否与sa[i-1]分别属于两个不同的字符串,如果是则比较得ans。

       时间复杂度为O(nlogn)。

           Ps:注意不能直接取height的最大值,因为取到的两个后缀的lcp可能同处于一个字符串。

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     5 using namespace std;
     6 
     7 const int maxn = 300000+10; 
     8 const int maxm = 150;
     9 
    10 int s[maxn];
    11 int sa[maxn],c[maxm],t[maxn],t2[maxn];
    12 
    13 void build_sa(int m,int n) {
    14     int i,*x=t,*y=t2;
    15     for(i=0;i<m;i++) c[i]=0;
    16     for(i=0;i<n;i++) c[x[i]=s[i]]++;
    17     for(i=1;i<m;i++) c[i]+=c[i-1];
    18     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    19     
    20     for(int k=1;k<=n;k<<=1) {
    21         int p=0;
    22         for(i=n-k;i<n;i++) y[p++]=i;
    23         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
    24         
    25         for(i=0;i<m;i++) c[i]=0;
    26         for(i=0;i<n;i++) c[x[y[i]]]++;
    27         for(i=0;i<m;i++) c[i]+=c[i-1];
    28         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
    29         
    30         swap(x,y);
    31         p=1; x[sa[0]]=0;
    32         for(i=1;i<n;i++) 
    33             x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
    34         if(p>=n) break;
    35         m=p;
    36     }
    37 }
    38 int rank[maxn],height[maxn];
    39 void getHeight(int n) {
    40     int i,j,k=0;
    41     for(i=0;i<=n;i++) rank[sa[i]]=i;
    42     for(i=0;i<n;i++) {
    43         if(k) k--;
    44         j=sa[rank[i]-1];
    45         while(s[j+k]==s[i+k]) k++;
    46         height[rank[i]]=k;
    47     }
    48 }
    49 
    50 char a[maxn],b[maxn];
    51 int n;
    52 
    53 int main() {
    54     scanf("%s%s",a,b);
    55     int lena=strlen(a),lenb=strlen(b);
    56     n=lena+lenb+1;
    57     for(int i=0;i<lena;i++) s[i]=a[i]; s[lena]=1;
    58     for(int i=0;i<lenb;i++) s[lena+i+1]=b[i];
    59     s[n]=0;
    60     
    61     build_sa('z'+1,n+1);
    62     getHeight(n);
    63     
    64     int ans=0;
    65     for(int i=2;i<=n;i++) {
    66         int k=0;
    67         k+=sa[i]<lena?1:2;
    68         k+=sa[i-1]<lena?1:2;
    69         if(k==3) ans=max(ans,height[i]);
    70     }
    71     printf("%d
    ",ans);
    72     return 0;
    73 }

    UPD.16/4/6

    当然也可以用SAM搞一搞,写起来更简单些

  • 相关阅读:
    FreeModbus TCP
    C#之用户自定义控件
    使用C库制作DLL
    C# Unable to load DLL 'WzCanDll.dll':找不到指定的模块
    C#之改变窗体icon图标、新建类文件、调用dll库
    sim800c GPRS模块的透传模式
    STM32上使用JSON
    STM32之串口IAP更新升级
    Fortran语言的REWIND和BACKSPACE 函数
    Code blocks 编译Fortran(转载)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5003121.html
Copyright © 2011-2022 走看看