Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2549    Accepted Submission(s): 1030

Problem Description
035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover,such apearances can not overlap each other.
Take aaaa as an example.”a” apears four times,”aa” apears two times without overlaping.however,aaa can’t apear more than one time without overlaping.since we can get “aaa” from [0-2](The position of string begins with 0) and [1-3]. But the interval [0-2] and [1-3] overlaps each other.So “aaa” can not take into account.Therefore,the answer is 2(“a”,and “aa”).
 
Input
The input data consist with several test cases.The input ends with a line “#”.each test case contain a string consists with lower letter,the length n won’t exceed 1000(n <= 1000).
 
Output
For each test case output an integer ans,which represent the answer for the test case.you’d better use int64 to avoid unnecessary trouble.
 
Sample Input
aaaa
ababcabb
aaaaaa
#
 
Sample Output
2
3
3
 
Source
 

思路:熟悉heigh数组就好了。枚举子串的长度k,将heigh数组按顺序分组,若该组的heigh值都大于等于k,则具有长度为k的公共前缀。比如heigh:3,2,3,1,2,0,1  当k=2时,分成(3,2,3) (1) (2) (0,1)

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int x = ;
const int maxn = ;
int t1[maxn], t2[maxn], c[maxn];
bool cmp(int *r, int a, int b, int l) {
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(char str[], int sa[], int Rank[], int heigh[], int n, int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[ x[i] = str[i] ]++;
for(int i = ; i < m; ++i) c[i] += c[i - ];
for(int i = n - ; i >= ; --i) sa[--c[x[i]]] = i; for(int j = ; j <= n; j <<= )
{
p = ;
for(i = n - j; i < n; ++i) y[p++] = i;
for(i = ; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[x[y[i]]]++;
for(i = ; i < m; ++i) c[i] += c[i - ];
for(i = n - ; i >= ; --i) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[ sa[] ] = ;
for(i = ; i < n; ++i)
x[ sa[i] ] = cmp(y, sa[i - ], sa[i], j) ? p - : p++;
if(p >= n) break;
m = p;
}
int k = ;
n--;
for(i = ; i <= n; ++i) Rank[ sa[i] ] = i;
for(i = ; i < n; ++i) {
if(k) k--;
j = sa[Rank[i] - ];
while(str[i + k] == str[j + k]) k++;
heigh[ Rank[i] ] = k;
}
} int Rank[maxn], heigh[maxn], sa[maxn];
char s[maxn];
void out(int n) {
///Rank数组的有效范围是0~n-1, 值是1~n
for(int i = ; i <= n; ++i) printf("%d ", Rank[i]);
puts("");
///sa数组的有效范围是1~n,值是0~n-1
for(int i = ; i <= n; ++i) printf("%d ", sa[i]);
puts("");
///heigh数组的有效范围是2~n
for(int i = ; i <= n; ++i) printf("%d ", heigh[i]);
}
int calc(int k, int n) {
int mi = INF, mx = -INF, res = ;
for(int i = ; i <= n; ++i) {
if(heigh[i] >= k) {
mi = min(mi, min(sa[i - ], sa[i]));
mx = max(mx, max(sa[i - ], sa[i]));
}else {
if(mx - mi >= k) res++;
mx = -INF, mi = INF;
}
}
if(mi != INF && mx - mi >= k) res++;
return res;
}
int main()
{
// freopen("in.txt", "r", stdin);
//freopen("out2.txt", "w", stdout);
while(scanf("%s", s)) {
if(strcmp(s, "#") == ) break;
int n = strlen(s);
da(s, sa, Rank, heigh, n, );
// out(n);
int ans = ;
for(int i = ; i <= (n >> ); ++i) ans += calc(i, n);
printf("%d\n", ans);
}
return ;
}

一开始的做法是hash+map,n^2logn会tle? 不明觉厉,暂时保存一下,忘指点。。。

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int x = ;
const int maxn = ;
ull H[maxn], xp[maxn];
map<ull, pair<int, int> > m;
int len;
char s[maxn];
void init() {
xp[] = ;
for(int i = ; i <= ; ++i) xp[i] = xp[i - ] * x;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out1.txt", "w", stdout);
init();
while(scanf("%s", s)) {
if(strcmp(s, "#") == ) break;
len = strlen(s);
H[len] = ;
for(int i = len - ; i >= ; --i) H[i] = H[i + ] * x + (s[i]);
m.clear();
long long ans = ;
for(int k = ; k <= len / ; ++k) {
for(int i = ; i <= len - k; i++) {
ull hash = H[i] - H[i + k] * xp[k];
int lp = m[hash].first;
int is = m[hash].second;
if(is == && i >= lp + k) {
m[hash].second = -;
ans++;
}else if(is == -) {
continue;
}else if(is == ) {
m[hash].first = i;
m[hash].second = ;
}
}
}
printf("%I64d\n", ans);
}
return ;
}

poj1743

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int x = ;
const int maxn = + ;
int t1[maxn], t2[maxn], c[maxn];
bool cmp(int *r, int a, int b, int l) {
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int str[], int sa[], int Rank[], int heigh[], int n, int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[ x[i] = str[i] ]++;
for(int i = ; i < m; ++i) c[i] += c[i - ];
for(int i = n - ; i >= ; --i) sa[--c[x[i]]] = i; for(int j = ; j <= n; j <<= )
{
p = ;
for(i = n - j; i < n; ++i) y[p++] = i;
for(i = ; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[x[y[i]]]++;
for(i = ; i < m; ++i) c[i] += c[i - ];
for(i = n - ; i >= ; --i) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[ sa[] ] = ;
for(i = ; i < n; ++i)
x[ sa[i] ] = cmp(y, sa[i - ], sa[i], j) ? p - : p++;
if(p >= n) break;
m = p;
}
int k = ;
n--;
for(i = ; i <= n; ++i) Rank[ sa[i] ] = i;
for(i = ; i < n; ++i) {
if(k) k--;
j = sa[Rank[i] - ];
while(str[i + k] == str[j + k]) k++;
heigh[ Rank[i] ] = k;
}
} int Rank[maxn], heigh[maxn], sa[maxn];
int s[maxn];
void out(int n) {
///Rank数组的有效范围是0~n-1, 值是1~n
for(int i = ; i <= n; ++i) printf("%d ", Rank[i]);
puts("");
///sa数组的有效范围是1~n,值是0~n-1
for(int i = ; i <= n; ++i) printf("%d ", sa[i]);
puts("");
///heigh数组的有效范围是2~n
for(int i = ; i <= n; ++i) printf("%d ", heigh[i]);
}
int flag, ans;
bool check(int k, int n) {
flag = ;
int mi = INF, mx = -INF;
for(int i = ; i <= n; ++i) {
if(heigh[i] >= k) {
mi = min(mi, min(sa[i - ], sa[i]));
mx = max(mx, max(sa[i - ], sa[i]));
}else {
if(mx - mi >= k + ) return true;
mx = -INF, mi = INF;
}
}
if(mi != INF && mx - mi >= k + ) return true;
return false;
}
void solve(int n) {
int L = , R = n + ;
while(R - L > ) {
int M = (L + R) >> ;
if(check(M, n)) L = M;
else R = M;
}
ans = L;
}
int main() {
int n;
while(~scanf("%d", &n) && n) {
for(int i = ; i < n; ++i) scanf("%d", &s[i]);
for(int i = ; i < n - ; ++i) {
s[i] = s[i + ] - s[i];
s[i] += ;
}
//for(int i = 0; i < n - 1; i++) printf("%d ", s[i]);
n--;
s[n] = ;
da(s, sa, Rank, heigh, n, );
solve(n);
if(ans + < ) puts("");
else
printf("%d\n", ans + );
}
return ;
}

hdu 3518 Boring counting 后缀数组基础题的更多相关文章

  1. hdu 3518 Boring counting 后缀数组LCP

    题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output ...

  2. hdu 3518 Boring counting 后缀数组

    题目链接 根据height数组的性质分组计算. #include <iostream> #include <vector> #include <cstdio> #i ...

  3. hdu 3518 Boring counting 后缀数组 height分组

    题目链接 题意 对于给定的字符串,求有多少个 不重叠的子串 出现次数 \(\geq 2\). 思路 枚举子串长度 \(len\),以此作为分界值来对 \(height\) 值进行划分. 显然,对于每一 ...

  4. 后缀数组 --- HDU 3518 Boring counting

    Boring counting Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,求:至少出 ...

  5. HDU 3518 Boring counting(后缀数组,字符处理)

    题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...

  6. HDU 3518 Boring counting

    题目:Boring counting 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 题意:给一个字符串,问有多少子串出现过两次以上,重叠不能算两次 ...

  7. hdu3518 Boring counting(后缀数组)

    Boring counting 题目传送门 解题思路 后缀数组.枚举每种长度,对于每个字符串,记录其最大起始位置和最小起始位置,比较是否重合. 代码如下 #include <bits/stdc+ ...

  8. poj 2774 Long Long Message 后缀数组基础题

    Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limi ...

  9. HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)

    Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

随机推荐

  1. IOS- 内存管理机制

    iOS平台内存常见问题 作为iOS平台的开发者,是否曾经为内存问题而苦恼过?内存莫名的持续增长,程序莫名的crash,难以发现 的内存泄漏,这些都是iOS平台内存相关的常见问题:本文将会详细介绍iOS ...

  2. innodb之超时参数配置

    可参考:http://www.penglixun.com/tech/database/mysql_timeout.html 下面内容摘取自上面这个链接. connection_timeout,只是设置 ...

  3. valgrind检查C++内存泄漏

    valgrind --tool=memcheck --leak-check=full ./httptest Valgrind 使用 用法: valgrind [options] prog-and-ar ...

  4. Java注释@interface的用法

    转---------- java用  @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类.@Override,@Deprecated,@Suppr ...

  5. 再来一发!DB2 应用程序如何从数据库取数据 Fetch

    The FETCH statement positions a cursor on the next row of its result table and assigns the values of ...

  6. service(启动方式)

  7. CLR via C#(07)-静态类,分部类

    一.      静态类-Static 静态类是一些不能实例化的类,它的作用是将一些相关的成员组合到一起,像我们常见的Math, Console等.静态类由static关键字标识,静态类成员也只能是st ...

  8. ASP.NET Web API 使用Swagger生成在线帮助测试文档

    Swagger-UI简单而一目了然.它能够纯碎的基于html+javascript实现,只要稍微整合一下便能成为方便的API在线测试工具.项目的设计架构中一直提倡使用TDD(测试驱动)原则来开发,sw ...

  9. 【JAVA集合框架之List】

    一.List接口概述. List有个很大的特点就是可以操作角标. 下面开始介绍List接口中相对于Collection接口比较特别的方法.在Collection接口中已经介绍的方法此处就不再赘述. 1 ...

  10. hdu 1247:Hat’s Words(字典树,经典题)

    Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...