ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】
SETI
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
Output
Sample Input
abacabacaba
Sample Output
15
Source
#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——————【后缀数组,不重叠重复子串个数】的更多相关文章
- [ACDream 1430]SETI 后缀数组
题目链接:http://acdream.info/problem?pid=1430 题目大意:给你一个长度不超过10000的字符串,问你出现过两次或两次以上的不重叠的子串有多少个. 后缀数组计算出he ...
- acdream 1430 SETI 后缀数组+height分组
这题昨天比赛的时候逗了,后缀想不出来,由于n^2的T了,就没往后缀数组想--并且之后解题的人又说用二分套二分来做.然后就更不会了-- 刚才看了题解,唉--原来题讲解n^2的也能够过,然后就--这样了! ...
- 【SPOJ – REPEATS】 后缀数组【连续重复子串】
字体颜色如何 字体颜色 SPOJ - REPEATS 题意 给出一个字符串,求重复次数最多的连续重复子串. 题解 引自论文-后缀数组--处理字符串的有力工具. 解释参考博客 "S肯定包括了字 ...
- SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数
题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- poj 1743 后缀数组 求最长不重叠重复子串
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. “主题”是整个音符序列的一个子串,它需要满足如下条件:1 ...
- poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)
题目链接:http://poj.org/problem?id=1743 题目理解起来比较有困难,其实就是求最长有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1 ...
- SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转
694. Distinct Substrings Problem code: DISUBSTR Given a string, we need to find the total number o ...
随机推荐
- springMVC绑定json参数之二(2.2.2)
二.springmvc 接收不同格式的json字符串 2).格式二:json字符串数组 前台: test = function () { var test = ["123",&qu ...
- 如何从光盘本地安装CentOS 7图形界面(Gnome GUI)
本例中通过在CentOS 7中修改repo文件,直接从光盘或者ISO镜像文件安装Gnome图形界面(Gnome GUI),从而避免耗时从官网或镜像下载. 1.首先确保光盘或者ISO镜像文件正确连接到客 ...
- mongodb 查询数据
MongoDB概念解析: 等同于SQL的数据库表:collectiondocument:等同于SQL的数据记录行field:等同于SQL的数据字段表连接,MongoDB不支持主键,MongoDB自动将 ...
- Spring框架IOC容器和AOP解析 非常 有用
Spring框架IOC容器和AOP解析 主要分析点: 一.Spring开源框架的简介 二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面 ...
- android studio在windows上设置git/ssh
windows果然是与众不同的,凡事都要那么麻烦一点点(当然..是对程序员来说..) 一开始,我想用cygwin里的git,就省得我再多装一套软件,配置也可以统一,但事实证明不行 在android s ...
- 12、scala隐式转换与隐式参数
一.隐式转换 1.介绍 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象. 通过这些功能,可以实 ...
- Java对象在内存中的状态
可达的/可触及的 Java对象呗创建后,如果被一个或者多个变量引用,那就是可达的,即从根节点可以触及到这个对象. 其实就是从根节点扫描,只要这个对象在引用链中,那就是可触及的. 可恢复的 Java对象 ...
- SCSS 中的 &::before 和 &::after
在看一个文件的时候,发现有&::before 和 &::after, 没有理解怎么用的,因为以前在项目的css文件中,从来没有使用过,也没有见过 网上查询了一下,才发现&::b ...
- node安装和配置
windows 环境 安装node node下载地址 下载后点击安装,默认下一步即可(安装路径可更改为d:盘) 检测PATH环境变量是否配置了Node.js 点击开始=>运行=>输入&qu ...
- 【java数据类型和mysqk数据类型对照表】
java mysql 数据类型对照 类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述 VARCHAR L+N VARCHAR java.lan ...