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) ...
随机推荐
- 【leetcode】Rotate List(middle)
Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...
- 【编程题目】在从 1 到 n 的正数中 1 出现的次数
30.在从 1 到 n 的正数中 1 出现的次数(数组)题目:输入一个整数 n,求从 1 到 n 这 n 个整数的十进制表示中 1 出现的次数.例如输入 12,从 1 到 12 这些整数中包含 1 的 ...
- JavaScript for循环里边异步操作问题。
问题:(DRIVING.search是异步操作) for循环中做异步操作会导致aDistances数组里边的数据全部都是从A_SHOP_INFO数组中最后一条数据获取的值. var iIdx = 0; ...
- SQL Server 2008 R2 安装出错:Could not open key
安装Sql Server 2008 R2 企业版出现错误提示无法继续安装,错误提示为: Could not open key: UNKNOWN\Components\7ABFE44842C12B390 ...
- pod install 慢
最近使用CocoaPods来添加第三方类库,无论是执行pod install还是pod update都卡在了Analyzing dependencies不动 原因在于当执行以上两个命令的时候会升级Co ...
- September 10th 2016 Week 37th Saturday
An innovation that goes beyond imagination again raised the standard. 颠覆想象的创新,再一次刷新标准. An advertisem ...
- centOS填坑笔记(一)
第一次使用centOS安装软件时,对二进制包的./configure进行配置时(./configure是源代码安装的第一步,主要的作用是对即将安装的软件进行配置,)报错:WARNING: failed ...
- JAVA一些常用的时间操作
项目中经常有对时间进行处理的需求,下面是一些常用的操作整理,方便以后再次使用以及做相关复习. 1.字符串转换为日期 /** * 字符串转换为日期 * @param dateStr 需要转换的日期 * ...
- 与你相遇好幸运,async解决循环回调问题
由于使用的sailsjs框架,用的是sailsjs自身带的ORm(就是waterline),ORM的默认数据库的返回值在回调里面. > arg是一个数组 count用来计数用 tmpArr临时存 ...
- iscroll 4.0 滚动(水平和垂直)
1.概述 iscroll 专注于页面滚动js.Iscroll滚动做的挺好,特别是针对手机网页(android.iphone)正好弥补手动滑屏的遗缺,而今研究一番,把代码贴出来,供大家参考. 2.isc ...