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. SlimDX.dll安装之后所在位置

    C:\Windows\Microsoft.NET\assembly\GAC_64\SlimDX\v4.0_4.0.13.43__b1b0c32fd1ffe4f9\SlimDX.dll

  2. Web 项目下载图片简单处理方式

    1.如果图片头信息有 "Content-Disposition", "attachment; filename="fileName" 那么直接使用 i ...

  3. SQLServer索引

    SQLServer索引1.聚集和非聚集索引聚集索引:根据聚集索引进行排序,非聚集索引因为不根据索引键排序,所以聚集索引比非聚集索引快(一个表只有一个聚集索引)2.唯一索引和非唯一索引唯一索引时值不能重 ...

  4. linux cpuInfo

    转自:http://blog.csdn.net/lgstudyvc/article/details/7889364   /proc/cpuinfo文件分析 在Linux系统中,提供了proc文件系统显 ...

  5. poj 3984:迷宫问题(广搜,入门题)

    迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7635   Accepted: 4474 Description ...

  6. 【ubuntu 】常见错误--Could not get lock /var/lib/dpkg/lock

    ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock 通过终端安装程序sudo apt-get install xxx时出错: E: Could not ...

  7. Centos 上使用Mono+MVC5+WebApi+Sqlite

    鉴于现在网上很多Mono安装Jexus的方法已经过时,你打开百度搜索基本是几个前辈写的文字,很多其实是过去式了.踩的坑多自然使人望而生畏,而方便快捷的方法百度排名却太低,这里就安利下笔者刚成功使用的方 ...

  8. PHP二维数组去除重复,重复值相加

    $arr = array( array('id' => 122, 'name' => '张三', 'amount' => '1'), array('id' => 123, 'n ...

  9. Parallel.js初探续集

    @author mrbean 例子均来源于github parallel.js 昨天写的第一篇今天一看居然有50+的阅读量了,感觉很激动啊,但是也有点害怕毕竟这只是自己笔记性质的一点东西,所以赶紧拿起 ...

  10. ASP.NET 5探险(2):上传文件

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:在ASP.NET 5(MVC 6)中处理上传文件的方式和之前有所不同. 在MVC 5之 ...