• bjoi 2010 外星联络 后缀数组


    题意:小 P 在看过电影《超时空接触》(Contact)之后被深深的打动,决心致力于寻 找外星人的事业。于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星 人发来的信息。虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高 低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在 其中。他认为,外星人发来的信息一定会在他接受到的 01 串中重复出现,所以 他希望找到他接受到的 01 串中所有重复出现次数大于 1 的子串。但是他收到的 信号串实在是太长了,于是,他希望你能编一个程序来帮助他。

    思路:后缀数组

    求出height,从前往后扫

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 using namespace std;
     6 #define MAXN 6100
     7 int n;
     8 char a[MAXN];
     9 int tmp[MAXN],cnt[MAXN],suffix_array[MAXN],rank[MAXN],oldrank[MAXN],memo[2],height[MAXN];
    10 bool use[MAXN/2][MAXN/2];
    11 void make_suffix_array()
    12 {
    13     memo[0]=memo[1]=0;
    14     memset(rank,0,sizeof(rank));
    15     memset(oldrank,0,sizeof(oldrank));
    16     int i,l;
    17     for(i=1;i<=n;i++) memo[a[i]]=1;
    18     memo[1]+=memo[0];
    19     for(i=1;i<=n;i++) rank[i]=memo[a[i]];
    20     for(l=1;l<=n;l*=2)
    21     {
    22 memset(cnt,0,sizeof(cnt)); 23 for(i=1;i<=n;i++) cnt[rank[i+l]]++; 24 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; 25 for(i=n;i>0;i--) tmp[cnt[rank[i+l]]--]=i; 26 27 memset(cnt,0,sizeof(cnt)); 28 for(i=1;i<=n;i++) cnt[rank[tmp[i]]]++; 29 for(i=1;i<=n;i++) cnt[i]+=cnt[i-1]; 30 for(i=n;i>0;i--) suffix_array[cnt[rank[tmp[i]]]--]=tmp[i]; 31 32 memcpy(oldrank,rank,sizeof(rank)); 33 rank[suffix_array[1]]=1; 34 int k=1; 35 for(i=2;i<=n;i++) 36 { 37 int x=suffix_array[i],y=suffix_array[i-1]; 38 if(oldrank[x]!=oldrank[y]||oldrank[x+l]!=oldrank[y+l]) k++; 39 rank[x]=k; 40 } 41 if(k==n) break; 42 } 43 } 44 void LCP() 45 { 46 int i,j,k=0; 47 a[n+1]=2; 48 for(i=1;i<=n;i++) 49 { 50 if(rank[i]==n) 51 { 52 height[n]=k=0; continue; 53 } 54 j=suffix_array[rank[i]+1]; 55 k=max(k-1,0); 56 while(a[i+k]==a[j+k]) k++; 57 height[rank[i]]=k; 58 } 59 } 60 void solve() 61 { 62 memset(use,0,sizeof(use)); 63 int i,j,k,ans; 64 for(i=1;i<n;i++) 65 { 66 for(j=1;j<=height[i];j++) 67 if(!use[i][j]&&!use[i+1][j]) 68 { 69 ans=2; 70 use[i][j]=use[i+1][j]=1; 71 for(k=i+1;k<=n;k++) 72 { 73 if(height[k]>=j) 74 ans++,use[k+1][j]=1; 75 else break; 76 } 77 printf("%d\n",ans); 78 } 79 80 } 81 } 82 int main() 83 { 84 scanf("%d",&n); 85 scanf("%s",a); 86 int i; 87 for(i=n;i>0;i--) a[i]=a[i-1]-48; 88 make_suffix_array(); 89 LCP(); 90 solve(); 91 return 0; 92 }
  • 相关阅读:
    Redis集群的三种模式
    导航
    关于Django数据库mysql连接错误问题Connection to api@localhost failed. [08001] Could not create connection to d
    原码 反码 补码(宁宝宝)
    CSS实现限制显示的字数,超出显示
    flask源码系列
    django入门
    包的用法
    小技巧分享持续更新
    drf源码系列
  • 原文地址:https://www.cnblogs.com/myoi/p/2444358.html
Copyright © 2020-2023  润新知