【BZOJ-2251】外星联络 后缀数组 + 暴力

2251: [2010Beijing Wc]外星联络

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 670  Solved: 392
[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

Solution

后缀数组..套路求完SA,height后暴力一下

求一个字串出现的次数,只要从该字串第一次出现的时候 暴力往后匹配即可

所以枚举排名为i的起点,从height[i]+1开始算就好了...至于为什么要+1,如果直接从height开始算.SA[i]和SA[i-1]开头的串会重复计算,所以要+1

Code

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 3010
char S[maxn];int SA[maxn],N;
int wa[maxn],wb[maxn],ws[maxn],wv[maxn];
int cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void DA(char *r,int *sa,int n,int m)
{
    int p,*x=wa,*y=wb,*t;
    for (int i=0; i<m; i++) ws[i]=0;
    for (int i=0; i<n; i++) ws[x[i]=r[i]]++;
    for (int i=1; i<m; i++) ws[i]+=ws[i-1];
    for (int i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
    p=1; for (int j=1; p<n; j*=2,m=p)
        {
            p=0; for (int i=n-j; i<n; i++) y[p++]=i;
            for (int i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j;
            for (int i=0; i<n; i++) wv[i]=x[y[i]];
            for (int i=0; i<m; i++) ws[i]=0;
            for (int i=0; i<n; i++) ws[wv[i]]++;
            for (int i=1; i<m; i++) ws[i]+=ws[i-1];
            for (int i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
            t=x,x=y,y=t;p=1;x[sa[0]]=0;
            for (int i=1; i<n; i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
}
int rank[maxn],height[maxn];
void calheight(char *r,int *sa,int n)
{
    int k=0;
    for (int i=1; i<=n; i++) rank[sa[i]]=i;
    for (int i=0; i<n; height[rank[i++]]=k)
        {k?k--:0;for (int j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);}
}
int main()
{
    scanf("%d",&N); scanf("%s",S);
    for (int i=0; i<N; i++) S[i]=S[i]-‘0‘+1; S[N]=0;
    DA(S,SA,N+1,3); calheight(S,SA,N);
    for (int i=1; i<=N; i++)
        for (int j=height[i]+1; SA[i]+j-1<=N; j++)
            {
                int l,r;
                for (l=i; height[l]>=j&&l>=1; l--);
                for (r=i+1; height[r]>=j&&r<=N; r++);
                if (r-l>1) printf("%d\n",r-l);
            }
    return 0;
}

悲伤的故事..手误打错一个字符...WA成狗还一直没看出来....最后气急败坏重新敲了一遍1A了...

时间: 2024-08-11 05:45:47

【BZOJ-2251】外星联络 后缀数组 + 暴力的相关文章

bzoj 2251: [2010Beijing Wc]外星联络 后缀数组

2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 424  Solved: 232[Submit][Status][Discuss] Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻 找外星人的事业.于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星 人发来的信息.虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高 低电平将接收到

BZOJ 2251 2010Beijing WC 外星联络 后缀数组/Trie树

题目大意 给出一个字符串,问这个字符串中出现过1次以上的子串的个数,按照子串的字典序输出. 思路 由于数据范围过小,这个题有两个解法. 基本的想法就是用后缀数组来进行后缀的排序,之后按照height数组扫就可以了.应该是挺快的. 但是注意到数据范围只有3000,因此我们只需要弄出所有的后缀拿出来建立一颗后缀Trie树就行了.最后DFS一次树种的所有节点. CODE SuffixArray #include <cstdio> #include <cstring> #include &

BZOJ 2251: [2010Beijing Wc]外星联络

2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 795  Solved: 477[Submit][Status][Discuss] Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻找外星人的事业.于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星人发来的信息.虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高低电平将接收到的信号

BZOJ 题目3172: [Tjoi2013]单词(AC自动机||AC自动机+fail树||后缀数组暴力||后缀数组+RMQ+二分等五种姿势水过)

3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1890  Solved: 877 [Submit][Status][Discuss] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6

【BZOJ2251】外星联络

2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 870  Solved: 524[Submit][Status][Discuss] Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻找外星人的事业.于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星人发来的信息.虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高低电平将接收到的信号

外星联络(bzoj 2251)

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

BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那

Bzoj2251 [2010Beijing Wc]外星联络

Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 867  Solved: 522 Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻找外星人的事业.于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星人发来的信息.虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在其中.他认为,外星人发来的信息一定会在他接受

BZOJ 3238 AHOI 2013 差异 后缀数组+单调栈

题目大意: 思路:一看各种后缀那就是后缀数组没跑了. 求出sa,height之后就可以乱搞了.对于height数组中的一个值,height[i]来说,这个值能够作为lcp值的作用域只在左边第一个比他小的位置到右边第一个比他小的位置.这个东西很明显可以倍增RMQ+二分/单调栈. 之后就是数学题了 Σlen[Ti] + len[Tj] = (len + 1) * len * (len - 1),之后吧所有求出来的Σ2 * lcp(Ti,Tj)减掉就是答案. 记得答案开long long CODE: