hdu 3518 Boring counting 后缀数组基础题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2549 Accepted Submission(s): 1030
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”).
思路:熟悉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 后缀数组基础题的更多相关文章
- hdu 3518 Boring counting 后缀数组LCP
题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output ...
- hdu 3518 Boring counting 后缀数组
题目链接 根据height数组的性质分组计算. #include <iostream> #include <vector> #include <cstdio> #i ...
- hdu 3518 Boring counting 后缀数组 height分组
题目链接 题意 对于给定的字符串,求有多少个 不重叠的子串 出现次数 \(\geq 2\). 思路 枚举子串长度 \(len\),以此作为分界值来对 \(height\) 值进行划分. 显然,对于每一 ...
- 后缀数组 --- HDU 3518 Boring counting
Boring counting Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,求:至少出 ...
- HDU 3518 Boring counting(后缀数组,字符处理)
题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...
- HDU 3518 Boring counting
题目:Boring counting 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 题意:给一个字符串,问有多少子串出现过两次以上,重叠不能算两次 ...
- hdu3518 Boring counting(后缀数组)
Boring counting 题目传送门 解题思路 后缀数组.枚举每种长度,对于每个字符串,记录其最大起始位置和最小起始位置,比较是否重合. 代码如下 #include <bits/stdc+ ...
- poj 2774 Long Long Message 后缀数组基础题
Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 24756 Accepted: 10130 Case Time Limi ...
- HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)
Boring counting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
随机推荐
- 9.27js拓展、bootstrap菜鸟教程
js(点击挂上 与 点击移除) <div id="dd" style="width:200px; height:200px; background-color:#6 ...
- UISrollView
1. contentOffset 默认CGPointZero,用来设置scrollView的滚动偏移量. // 设置scrollView的滚动偏移量 scrollView.contentOffset ...
- 解决java.lang.SecurityException: Access to default session denied
原先使用的代码如下: Session session = Session.getDefaultInstance(properties, null); 后来把代码修改为: Session session ...
- 1.1-java创建包和类的方法
1.new-package-命名方法com打头.中间名称.后台要创建的class 2.创建class- new-class 选择一下主方法 代码示例 编译完保存一下就能输出信息,一直没有保存才 ...
- 一个简单的jsp+servlet实例,实现简单的登录
开发环境myeclipse+tomcat6 1.先创建web project,项目名为RegisterSystem, 2.在WebRoot 目录下创建login.jsp文件,只需修改body中的内容, ...
- Android Programming: Pushing the Limits -- Chapter 1: Fine-Tuning Your Development Environment
ADB命令 Application Exerciser Monkey Gradle ProGuard 代码重用 版本控制 静态代码分析 代码重构 开发者模式 ADB命令: @.adb help:查 ...
- elk深度解析
上面的两张图是elk的一个架构 下面是对logstash分析:如下图 可以看出 logstash的一个角色shipper,(是通过配置文件来决定logstash是shipper还是indexer)注意 ...
- C#回顾 - 3.NET的IO:字节流
使用 Stream 类管理字节流 使用 FileStream 类管理文件数据 使用 MemoryStream 类管理内存数据 使用 BufferedSream 类提高流性能 3.1 FileStr ...
- 关于v$datafile中system表空间的status值始终为system
http://docs.oracle.com/cd/B19306_01/server.102/b14237/dynviews_1076.htm#REFRN30050 http://blog.itpub ...
- Delphi的属性Property
参考:http://www.cnblogs.com/edisonfeng/archive/2012/05/22/2513727.html 一.基本属性 TOnUserInfoShow = proced ...