zoukankan      html  css  js  c++  java
  • BZOJ2251: [2010Beijing Wc]外星联络

    2251: [2010Beijing Wc]外星联络

    Time Limit: 30 Sec  Memory Limit: 256 MB
    Submit: 989  Solved: 601
    [Submit][Status][Discuss]

    Description

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

    Input

    输入文件的第一行是一个整数N ,代表小 P 接收到的信号串的长度。
    输入文件第二行包含一个长度为N 的 01 串,代表小 P 接收到的信号串。

    Output

    输出文件的每一行包含一个出现次数大于1 的子串所出现的次数。输出的顺
    序按对应的子串的字典序排列。

    Sample Input

    7
    1010101

    Sample Output

    3
    3
    2
    2
    4
    3
    3
    2
    2

    HINT

      对于 100%的数据,满足 0 <=  N     <=3000 

    Source

    【题解】

    dalao们的题解:

    “吼罪素组直接暴腻即可”

    “裸题”

    ‘闲的没事了写一下证明吧’

    。。。。。。。。。。。。。。。。。。。。。。。。。。。

    此题把所有后缀提出来建一颗trie树还是比较好理解的一种做法,每个串的答案就是这个串末节点被走过的次数

    后缀数组通过每个后缀的前缀来处理子串,所有后缀的每个前缀构成全部非空子串

    于是我们尝试找与每个前缀相等的前缀

    按字典序排序后,从小到大取,当前取到sa[i],只需从sa[i] + height[i]开始枚举前缀长度l,在排好序的后缀上向右拓展,直到到达末尾或者某个height[j]<l为止

    为什么这样是对的呢?

    首先你需要画一张图样例的height图,跟着调试程序模拟一下,你会有一点点想法,然后看下面本蒟蒻十分辣鸡的假证明从sa[i] + height[i]开始,因为sa[i] + height[i] - 1一定在之前遍历过。先看边界,height[k] = 0的时刻,能遍历到height[k + 1]这些串

    设想如果height[i - 1] < height[i], 那么sa[i] + height[i-1]...sa[i] + height[i] - 1会被遍历;否则,无法遍历到,继续前推,肯定会到达height = 0的时刻,归纳证明可以遍历完。

    为什么向后扩展不向前扩展或者双向扩展呢?因为长度大于跟前面的LCP,前面肯定没有呀。。。

    大概这样。。大家可以拿图画画加深一下理解。。

    如有谬误,还请原谅,毕竟。。。

    我也不会很严谨的证明。。。

    换了一个SA板子,从1开始的,这样跟AC自动机统一起来了,以后除KMP外所有字符串题都可以从1开始了。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 #include <queue>
     7 #include <vector>
     8 #include <cmath> 
     9 #define min(a, b) ((a) < (b) ? (a) : (b))
    10 #define max(a, b) ((a) > (b) ? (a) : (b))
    11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
    12 
    13 template <class T>
    14 inline void swap(T& a, T& b)
    15 {
    16     T tmp = a;a = b;b = tmp;
    17 }
    18 
    19 const int INF = 0x3f3f3f3f;
    20 const int MAXN = 1000000 + 10;
    21 
    22 struct SuffixArray
    23 {
    24     char s[MAXN];
    25     int sa[MAXN], rank[MAXN], height[MAXN];
    26     int t1[MAXN], t2[MAXN], c[MAXN];
    27     int n;
    28     void build_sa(int m)
    29     {
    30         int i, *x = t1, *y = t2;
    31         for(i = 0;i <= m;++ i) c[i] = 0;
    32         for(i = 1;i <= n;++ i) ++ c[x[i] = s[i]];
    33         for(i = 1;i <= m;++ i) c[i] += c[i - 1];
    34         for(i = n;i >= 1;-- i) sa[c[x[i]] --] = i;
    35         for(int k = 1;k <= n;k <<= 1)
    36         {
    37             int p = 0;
    38             for(i = n - k + 1;i <= n;++ i) y[++ p] = i;
    39             for(i = 1;i <= n;++ i) if(sa[i] > k) y[++ p] = sa[i] - k;
    40             for(i = 0;i <= m;++ i) c[i] = 0;
    41             for(i = 1;i <= n;++ i) ++ c[x[y[i]]];
    42             for(i = 1;i <= m;++ i) c[i] += c[i - 1];
    43             for(i = n;i >= 1;-- i) sa[c[x[y[i]]] --] = y[i];
    44             swap(x, y);p = 0,x[sa[1]] = ++ p;
    45             for(i = 2;i <= n;++ i)
    46                 x[sa[i]] = sa[i] + k <= n && sa[i - 1] + k <= n && y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++ p;
    47             if(p >= n) break;m = p;
    48         }
    49     }
    50     void build_height()
    51     {
    52         int i, k = 0;
    53         for(i = 1;i <= n;++ i) rank[sa[i]] = i;
    54         for(i = 1;i <= n;++ i)
    55         {
    56             if(k) -- k; if(rank[i] == 1) continue;
    57             int j = sa[rank[i] - 1];
    58             while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++ k;
    59             height[rank[i]] = k;
    60         }
    61     }
    62 }A;
    63 
    64 int n;
    65 
    66 int main()
    67 {
    68     scanf("%d", &n);
    69     scanf("%s", A.s + 1);
    70     A.n = n;
    71     A.build_sa('1');
    72     A.build_height();
    73     int k;
    74     for(int i = 1;i <= n;++ i)
    75         for(int j = A.sa[i] + A.height[i];j <= n;++ j)
    76         {
    77             for(k = i;A.height[k + 1] >= j - A.sa[i] + 1;++ k);
    78             if(k - i + 1 > 1) printf("%d
    ", k - i + 1);
    79         }
    80                 
    81 }
    BZOJ2251
  • 相关阅读:
    python2.7下同步华为云照片的爬虫程序实现
    python 下字符串格式时间比较
    C# Socket通信 小案例
    win 10 安装 mysql解压版 步骤
    Android 连接 SQL Server (jtds方式)——下
    Android 连接 SQL Server (jtds方式)——上
    Android 项目建立步骤
    ubuntu 配置android开发环境
    ubuntu 安装eclipse
    ubuntu 配置Java jdk
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8333823.html
Copyright © 2011-2022 走看看