300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > BZOJ2251: [Beijing Wc]外星联络

BZOJ2251: [Beijing Wc]外星联络

时间:2018-09-30 13:32:19

相关推荐

BZOJ2251: [Beijing Wc]外星联络

2251: [Beijing Wc]外星联络

Time Limit: 30 SecMemory Limit: 256 MB

Submit: 989Solved: 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 {16T tmp = a;a = b;b = tmp;17 }18 19 const int INF = 0x3f3f3f3f;20 const int MAXN = 1000000 + 10;21 22 struct SuffixArray23 {24char s[MAXN];25int sa[MAXN], rank[MAXN], height[MAXN];26int t1[MAXN], t2[MAXN], c[MAXN];27int n;28void 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}50void 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 {68scanf("%d", &n);69scanf("%s", A.s + 1);70A.n = n;71A.build_sa('1');72A.build_height();73int k;74for(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\n", k - i + 1);79 }80 81 }

BZOJ2251

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。