POJ 3261 可重叠的 k 次最长重复子串【后缀数组】
这也是一道例题
给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠。
算法分析:
这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组。不
同的是,这里要判断的是有没有一个组的后缀个数不小于 k。如果有,那么存在
k 个相同的子串满足条件,否则不存在。这个做法的时间复杂度为 O(nlogn)。
我们可以通过二分子串的长度k来做,这时就将题目变成了是否存在重复次数至少为K次且长度不小k的字符串。
首先我们可以把相邻的所有不小于k的height[]看成一组,这组内有多少个字符串,
就相当于有多少个长度至少为k的重复的子串。
之所以可以这么做,是因为排名第i的字符串和排名第j的字符串的最长公共前缀
等于height[i],height[i+1],...,height[j]中的最小值,所以把所有不小于k的height[]看成
一组就保证了组内任意两个字符串的最长公共前缀都至少为k,且长度为k的前缀是每个字符串共有的,
因此这组内有多少个字符串,就相当于有多少个长度至少为k的重复的子串(任意一个子串都是某个后缀的前缀)。
Source Code:
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <algorithm>
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
#define MOD 1000000007
#define pi acos(-1.0) using namespace std; typedef long long ll ;
typedef unsigned long long ull ;
typedef unsigned int uint ;
typedef unsigned char uchar ; template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}
template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;} const double eps = 1e- ;
const int N = ;
const int M = ;
const ll P = 10000000097ll ;
const int INF = 0x3f3f3f3f ; int a[M], sa[M], h[M], rank[M]; void radix(int *str, int *a, int *b, int n, int m){
static int count[M];
int i;
memset(count, , sizeof(count));
for(i = ; i < n; ++i) ++count[str[a[i]]];
for(i = ; i <= m; ++i) count[i] += count[i - ];
for(i = n - ; i >= ; --i) b[--count[str[a[i]]]] = a[i];
} void suffix_array(int *str, int *sa, int n, int m){
static int a[M], b[M];
int i, j;
for(i = ; i < n; ++i) rank[i] = i;
radix(str, rank, sa, n, m); rank[sa[]] = ;
for(i = ; i < n; ++i) rank[sa[i]] = rank[sa[i - ]] + (str[sa[i]] != str[sa[i - ]]);
for(i = ; <<i < n; ++i){
for(j = ; j < n; ++j){
a[j] = rank[j] + ;
b[j] = j + ( << i) >= n ? : rank[j + ( << i)] + ;
sa[j] = j;
}
radix(b, sa, rank, n, n);
radix(a, rank, sa, n, n);
rank[sa[]] = ;
for(j = ; j < n; ++j){
rank[sa[j]] = rank[sa[j - ]] + (a[sa[j - ]] != a[sa[j]] || b[sa[j - ]] != b[sa[j]]);
}
}
} void calc_height(int *str, int *sa, int *h, int n){
int i, k = ;
h[] = ;
for(i = ; i < n; ++i){
k = k == ? : k - ;
if(rank[i] != ){
while(str[i + k] == str[sa[rank[i] - ] + k]){
++k;
}
}
h[rank[i]] = k;
}
} void solve_duplicate_substr(int n){
int i, j, pos, ans = ;
for(i = ; i < n; ++i){
if(h[rank[i]] > ans){
ans = h[rank[i]];
pos = i;
}
}
for(i = pos; i < pos + ans; ++i){
printf("%c", a[i]);
}
printf("\n");
} void slove_update_duplicate_substr(int n, int k){
int i, j;
int low = , high = n;
int ans = , pos1 = , pos2 = ;
while(low <= high){
int mid = (low + high) / ;
bool flag = false;
for(i = ; i < n; ++i){
if(h[i] >= mid){
++ans;
if(ans >= k) flag = true;
}
else ans = ;
}
if(flag) low = mid + ;
else high = mid - ;
}
cout << high << endl;
} int main(){
int i, j, t, n, m, k;
while(cin >> n >> k){
for(i = ; i < n; ++i) cin >> a[i];
suffix_array(a, sa, n, );
calc_height(a, sa, h, n);
slove_update_duplicate_substr(n, k);
}
return ;
}
POJ 3261 可重叠的 k 次最长重复子串【后缀数组】的更多相关文章
- POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7586 Accepted: 3448 Cas ...
- 【POJ 3261】Milk Patterns 可重叠的k次最长重复子串
可重叠的k次最长重复子串 #include<cstdio> #include<cstring> #include<algorithm> using namespac ...
- poj 3261 后缀数组 可重叠的 k 次最长重复子串
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16430 Accepted: 7252 Ca ...
- poj 3261 求可重叠的k次最长重复子串
题意:求可重叠的k次最长重复子串的长度 链接:点我 和poj1743差不多 #include<cstdio> #include<iostream> #include<al ...
- 后缀数组练习2:可重叠的k次最长重复子串
其实和上一题是差不多的,只是在二分check的时候有一些小小的改动 1468: 后缀数组2:可重叠的k次最长重复子串 poj3261 时间限制: 1 Sec 内存限制: 128 MB提交: 113 ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组
http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...
- poj3261 Milk Patterns 后缀数组求可重叠的k次最长重复子串
题目链接:http://poj.org/problem?id=3261 思路: 后缀数组的很好的一道入门题目 先利用模板求出sa数组和height数组 然后二分答案(即对于可能出现的重复长度进行二分) ...
- POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16742 Accepted: 7390 Ca ...
随机推荐
- ASP.NET MVC5 学习笔记-3 Model
1. Model 1.1 添加一个模型 注意,添加属性时可以输入"prop",会自动输入代码段. public class CheckoutAccount { public int ...
- PowerShell Remove all user defined variable in PowerShell
When PS scripts executes, it is possibly create much user defined variables. So, sometimes these var ...
- 关于struts2的checkboxlist、select等标签发生could not be resolved as a collection/array/map/enumeration/iterator type异常的记录
1 刚进入该界面的时候发生错误,原因是 list="roles"中的这个集合是空的,导致错误 解决办法很简单,不能让list为空 2 刚进入该界面的时候list是有数据的,当点击提 ...
- ie6与固定定位fixed,+ 条件注释格式注意
ie6并不支持position:fixed, ie7+都支持fixed定位, ie6固定定位实现方法1: <!DOCTYPE html> <html> <head> ...
- Delphi 类型转换函数(有几个函数没见过,FloatToStrF,FloatToText等等)
Chr 将一个有序数据转换为一个ANSI字符 Ord 将一个有序类型值转换为它的序号 Round 转换一个实型值为四舍五入后的整型值 Trunc 转换一个实型值为小数截断后的整型值 Int 返回浮点数 ...
- (C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开
原文 (C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一篇:(C#)Windows Shell 编 ...
- APUE学习之---------------进程
离职了,交接期也有足够的时间了,可以在好好的再看一下APUE,想想上次详细的看还是在两年之前,虽然中间也偶尔会翻出来看看,但是由于工作上交集相对比较少一直没有去细读一下.现在正好是一段空挡期可以好好看 ...
- 用elasticsearch索引mongodb数据
参照网页:单机搭建elasticsearch和mongodb的river 三个步骤: 一,搭建单机replicSet二,安装mongodb-river插件三,创建meta,验证使用 第一步,搭建单机m ...
- 100% width CSS 在 iPad / iPhone Safari 背景被截断 / 显示不全
Tips: 调试 iPad 或 iPhone 可在设置中启动调试模式,在 Mac 中的 Safari 浏览器 同样开启开发者模式后,进行联机调试.功能彪悍. 最近在做一个页面时,发现在 iPad 的 ...
- php:根据中文裁减字符串函数方法
define(CHARSET, 'UTF-8'); // 系统默认编码 /** * 根据中文裁减字符串 * @param $string - 字符串 * @param $length - 长度 * @ ...