SETI

Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

Problem Description

Amateur astronomers Tom and Bob try to find radio broadcasts of extraterrestrial civilizations in the air. Recently they received some strange signal and represented it as a word consisting of small letters of the English alphabet. Now they wish to decode the signal. But they do not know what to start with.
      They think that the extraterrestrial message consists of words, but they cannot identify them. Tom and Bob call a subword of the message a potential word if it has at least two non-overlapping occurrences in the message.

For example, if the message is “abacabacaba”, “abac” is a potential word, but “acaba” is not because two of its occurrences overlap.
      Given a message m help Tom and Bob to find the number of potential words in it.

Input

      Input file contains one string that consists of small letters of the English alphabet. The length of the message doesn’t exceed 10 000.

Output

      Output one integer number — the number of potential words in a message.

Sample Input

abacabacaba

Sample Output

15

Source

Andrew Stankevich Contest 23
题目大意:给你一个串,让求该串的不重叠重复子串个数有多少个。
 
解题思路:后缀数组模板题。构造该字符串的height数组,然后枚举公共前缀长度为1---n/2的子串有多少个,累加结果。
 
 
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
const int maxn = 1e5+200;
const int INF = 0x3f3f3f3f;
char s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn];
int rank[maxn], height[maxn];
void build_sa(int n, int m){ //构造sa数组
int i,*x = t, *y = t2;
//初始化,基数排序
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1){
int p = 0;
//直接利用上次的sa数组排序第二关键字,得到本次的伪sa数组
for(i = n-k; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k; //y是伪sa数组
//基数排序第一关键字,利用本次伪sa数组和上次的排名数组得到本次的sa数组
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++; //这里的x数组类似于后来要求的rank数组
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
//交换后,y数组变为上次的排名数组,然后根据本次sa和上次的排名数组y得到本次的排名数组x
swap(x,y);
p = 1; x[sa[0]] = 0;
for(i =1; i < n; i++)
x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] ==y[sa[i]+k] ? p-1:p++;
if(p >= n) break;
m = p;
}
return ;
}
void getheight(int n) { int i, j, k = 0;
for(i = 0; i < n; i++) { //从i = 0 到 i = n-1是有用的
rank[sa[i]] = i;
}
for(i = 0; i < n; i++) {
if(k) k--;
int j = sa[rank[i]-1];
while(s[i+k] == s[j+k]){
k++;
}
height[rank[i]] = k;
}
}
int check(int mid , int n){
int mi=INF , mx = 0, num=0, ret = 0;
for(int i = 2;i <= n+1;i++){ //i = 2 因为最小的肯定是尾字符,所以i从2开始计算
if(i==n+1 || height[i] < mid){
// printf("%d %d %d\n",i,height[i],mid);
mi = min(mi, sa[i-1]);
mx = max(mx, sa[i-1]);
if(mx - mi >= mid &&num >= 1){ //mx - mi >= mid表示不重叠 num >= 1表示存在重复子串
ret ++;
}
mx = 0; mi = INF;
num = 0;
}
else if(height[i] >= mid){ //表示sa[i]跟sa[i-1]的公共前缀长度大于mid
mi = min(mi,sa[i-1]);
mx = max(mx,sa[i-1]);
num++;
}
}
return ret;
}
int main(){
int n;
while(scanf("%s",s)!=EOF){
n = strlen(s);
// s[n++] = '#';
// s[n] = '\0';
build_sa(n+1,200); //如果想让字符串结尾符'\0'作为尾字符,那么就传参n+1
build_sa(n, 200); //或者加一个'#'作为尾字符,传参n。 尾字符一定要是所有字符中最小的,且大于等于0 getheight(n+1); //跟构造sa同理 int ans = 0 ,res;
for(int i = 1; i <= n/2; i++){
if(res = check(i , n)){ //枚举各个公共前缀长度
// printf("%d %d+++\n", i, res);
ans += res;
}
}
printf("%d\n",ans);
}
return 0;
}

  

ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】的更多相关文章

  1. [ACDream 1430]SETI 后缀数组

    题目链接:http://acdream.info/problem?pid=1430 题目大意:给你一个长度不超过10000的字符串,问你出现过两次或两次以上的不重叠的子串有多少个. 后缀数组计算出he ...

  2. acdream 1430 SETI 后缀数组+height分组

    这题昨天比赛的时候逗了,后缀想不出来,由于n^2的T了,就没往后缀数组想--并且之后解题的人又说用二分套二分来做.然后就更不会了-- 刚才看了题解,唉--原来题讲解n^2的也能够过,然后就--这样了! ...

  3. 【SPOJ – REPEATS】 后缀数组【连续重复子串】

    字体颜色如何 字体颜色 SPOJ - REPEATS 题意 给出一个字符串,求重复次数最多的连续重复子串. 题解 引自论文-后缀数组--处理字符串的有力工具. 解释参考博客 "S肯定包括了字 ...

  4. SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数

    题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...

  5. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  6. POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)

    永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...

  7. poj 1743 后缀数组 求最长不重叠重复子串

    题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. “主题”是整个音符序列的一个子串,它需要满足如下条件:1 ...

  8. poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)

    题目链接:http://poj.org/problem?id=1743 题目理解起来比较有困难,其实就是求最长有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1 ...

  9. SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转

    694. Distinct Substrings Problem code: DISUBSTR   Given a string, we need to find the total number o ...

随机推荐

  1. Python模块-shelve模块

    shelve模块也是用来序列化的,可以持久化任何pickle可支持的python数据格式,比pickle好用,也是python专属,可以dump多次数据,也可以直接修改数据 序列化 # -*- cod ...

  2. JavaScript之使用JavaScript模仿oop编程

    第一, 首先,使用关键字function定义一个类 function Shape1(ax,ay) {//此时将function看成声明类的标志 ; ; var init=function () {// ...

  3. RubyGems 镜像 - 淘宝网

    为什么有这个? 由于国内网络原因(你懂的),导致 rubygems.org 存放在 Amazon S3 上面的资源文件间歇性连接失败.所以你会与遇到 gem install rack 或 bundle ...

  4. badblocks 检查磁盘损坏的区块

    Linux badblocks命令用于检查磁盘装置中损坏的区块. 语法: badblocks [-svw][-b <区块大小>][-o <输出文件>][磁盘装置][磁盘区块数] ...

  5. typeof用法

    typeof的运算数未定义,返回的就是 "undefined". 运算数为数字 typeof(x) = "number" 字符串 typeof(x) = &qu ...

  6. KickStart安装CentOS,同时安装和配置hadoop

    声明:这篇文章是前面是拾人牙慧,我是结合 http://www.111cn.net/sys/linux/59969.htm 和 http://www.cnblogs.com/mchina/p/cent ...

  7. Asp.net Core 使用 EntityFrameworkCore 1.1

    前言 相比大家也在开发中是非常喜欢用ORM的.今天就来介绍一下EntityFrameworkCore的使用方法. 自从EF Core升级到1.1之后,确实变化挺大的.如果没试过真的不知道坑是挺多的.今 ...

  8. Sharepoint2013商务智能学习笔记之简单概述(一)

    SharePoint 2013 中的商业智能 (BI) 提供集 Microsoft Office 应用程序和其他 Microsoft 技术于一体的全面的 BI 工具.这些 BI 工具有:Excel 2 ...

  9. kolla-build常用命令行详解

    --base-image 用于指定使用自己定制的基础镜像,不用官方网站的样例如下:kolla-build --base-image registry.access.redhat.com/rhel7/r ...

  10. Python中配置文件解析模块-ConfigParser

    Python中有ConfigParser类,可以很方便的从配置文件中读取数据(如DB的配置,路径的配置).配置文件的格式是: []包含的叫section, section 下有option=value ...