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. 【linux】虚拟机安装centos后ping ip地址出现错误:Network is unreachable

    来源:https://my.oschina.net/stonezing/blog/515480 方案一: 进入/etc/sysconfig/network-scripts/ 查看这下面的文件 每个人的 ...

  2. osg绘制一个球体

    //By smells2 at Lab 2012-02-21#include <osg/Group>#include <osg/Geode>#include <osg/S ...

  3. Linux解决关闭终端后终止服务问题

    可使用nohup. 具体使用方法,参见:http://zjking.blog.51cto.com/976858/1117828

  4. MongoDB csv文件导入导出

    1.导出到csv文件: 2.从csv导入: 数据经过csv导出导入,有一个非常隐蔽的问题,编写代码时需要注意: 先导入一条数据: 其中Price是double类型: 然后我把该条记录导出到Demo.c ...

  5. Android中通过反射获取资源Id

    package com.cp.utils; import android.content.Context; public class CPResourceUtil { public static in ...

  6. hdu1018(数位)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1018 题意:求n!的数位(即n!有多少位): 思路:对于一个数x,它的数位ans=log10(x): ...

  7. NYOJ题目65另一种阶乘问题

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsIAAAJhCAIAAADE+EHOAAAgAElEQVR4nO3drXLjSAMu4HMT4bmQYF

  8. tableView 局部刷新

    //一个section刷新 NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2]; [tableview reloadSections:in ...

  9. MySQL 主从同步

    http://blog.csdn.net/z69183787/article/details/53897894

  10. 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件(转)

    Mybatis属于半自动ORM,在使用这个框架中,工作量最大的就是书写Mapping的映射文件,由于手动书写很容易出错,我们可以利用Mybatis-Generator来帮我们自动生成文件. 1.相关文 ...