POJ 3261 Milk Patterns ( 后缀数组 && 出现k次最长可重叠子串长度 )
题意 : 给出一个长度为 N 的序列,再给出一个 K 要求求出出现了至少 K 次的最长可重叠子串的长度
分析 : 后缀数组套路题,思路是二分长度再对于每一个长度进行判断,判断过程就是对于 Height 数组进行限定长度的分组策略,如果有哪一组的个数 ≥ k 则说明可行!

分组要考虑到一个事实,对于每一个后缀,与其相匹配能够产生最长的LCP长度的串肯定是在后缀数组中排名与其相邻。
一开始对分组的理解有误,所以想了一个错误做法 ==>
遍历一下 Height 将值 ≥ (当前二分长度) 的做一次贡献即 cnt++ ,若最后 cnt ≥ K 说明可行。当然这个肯定是炸了.......
下面说说我对于 Height 分组的理解吧,就看上面的图,如果当前 K == 2,那么第一组的含义是什么?换句话说就是为什么那么些个后缀要属于一组?可以看出第一组里面的 Height 值都不会小于 K ,实际的意义呢应当是第一组里面的有一个长度为 2 (不小于K)的共同前缀,即 “aa” ,那么是不是 “aa” 这个子串可重叠地出现了 cnt 次(cnt为第一组的后缀个数),可能你已经有点体会到分组的意义了!那么有没有可能有些前缀是 “aa” 但是没有被分进第一组呢?看见上面红字描述的事实么?根据上面的那个事实,而且 Height 的下标是根据排名有序的这个特点(有序的意思就是从小到大遍历 Height 实际传进去的下标就是排名!即 Height[i],i是表示第 i 名的后缀),我们就知道这样的事情不会发生,且分出来的组肯定的“连续的块”,即不会有这一组的元素在其他地方的可能性!
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
;
int sa[maxn], s[maxn], wa[maxn], Ws[maxn], wv[maxn], wb[maxn];
int Rank[maxn], height[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 r[], int sa[], int n, int m)
{
int i, j, p, *x = wa, *y = wb;
; i < m; ++i) Ws[i] = ;
; i < n; ++i) Ws[x[i]=r[i]]++;
; i < m; ++i) Ws[i] += Ws[i-];
; i >= ; --i) sa[--Ws[x[i]]] = i;
, p = ; p < n; j *= , m = p)
{
, i = n - j; i < n; ++i) y[p++] = i;
; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
; i < n; ++i) wv[i] = x[y[i]];
; i < m; ++i) Ws[i] = ;
; i < n; ++i) Ws[wv[i]]++;
; i < m; ++i) Ws[i] += Ws[i-];
; i >= ; --i) sa[--Ws[wv[i]]] = y[i];
, x[sa[]] = , i = ; i < n; ++i)
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p- : p++;
}
}
void calheight(int r[], int sa[], int n)
{
;
; i <= n; ++i) Rank[sa[i]] = i;
; i < n; height[Rank[i++]] = k)
, j = sa[Rank[i]-]; r[i+k] == r[j+k]; k++);
}
bool IsOk(int len, int n, int aim)
{
;
// for(int i=2; i<=n; i++){ //错误的!
// if(height[i] >= len)
// if(++cnt >= aim)
// return true;
// }return false;
; i<=n; i++){
if(height[i] >= len){ if(++cnt >= aim) return true; }
;
}return false;
}
int arr[maxn];
int main(void)
{
int N, K;
while(~scanf("%d %d", &N, &K)){
; i<N; i++)
scanf("%d", &arr[i]);
da(arr, sa, N+, );
calheight(arr, sa, N);
, R = N, ans = -;
while(L <= R){
);
;
;
}
ans==-? puts(") : printf("%d\n", ans);
}
;
}
题目单个元素的值能达到 1e6 这么大,数组按这个开还勉强OK,但是这里还是要学学离散化的姿势!
离散化版:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
;
struct st{
int ord, val;
bool operator < (const st &rhs) const {
return this->val < rhs.val;
};
}arr[maxn];
int sa[maxn], s[maxn], wa[maxn], Ws[maxn], wv[maxn], wb[maxn];
int Rank[maxn], height[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 r[], int sa[], int n, int m)
{
int i, j, p, *x = wa, *y = wb;
; i < m; ++i) Ws[i] = ;
; i < n; ++i) Ws[x[i]=r[i]]++;
; i < m; ++i) Ws[i] += Ws[i-];
; i >= ; --i) sa[--Ws[x[i]]] = i;
, p = ; p < n; j *= , m = p)
{
, i = n - j; i < n; ++i) y[p++] = i;
; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
; i < n; ++i) wv[i] = x[y[i]];
; i < m; ++i) Ws[i] = ;
; i < n; ++i) Ws[wv[i]]++;
; i < m; ++i) Ws[i] += Ws[i-];
; i >= ; --i) sa[--Ws[wv[i]]] = y[i];
, x[sa[]] = , i = ; i < n; ++i)
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p- : p++;
}
}
void calheight(int r[], int sa[], int n)
{
;
; i <= n; ++i) Rank[sa[i]] = i;
; i < n; height[Rank[i++]] = k)
, j = sa[Rank[i]-]; r[i+k] == r[j+k]; k++);
}
bool IsOk(int len, int n, int aim)
{
;
; i<=n; i++){
if(height[i] >= len)
{ if(++cnt >= aim) return true; }
;
}return false;
}
int r[maxn];
int main(void)
{
int N, K;
while(~scanf("%d %d", &N, &K)){
; i<N; i++){
scanf("%d", &arr[i].val);
arr[i].ord = i;
}
;
sort(arr, arr+N);
; i<N; i++)
&& arr[i].val == arr[i-].val) r[arr[i].ord] = num; ///注意相等的时候如何处理
else r[arr[i].ord] = ++num;
da(r, sa, N+, num+);
calheight(r, sa, N);
, R = N, ans = -;
while(L <= R){
);
;
;
}
ans==-? puts(") : printf("%d\n", ans);
}
;
}
POJ 3261 Milk Patterns ( 后缀数组 && 出现k次最长可重叠子串长度 )的更多相关文章
- POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次
Milk Patterns Description Farmer John has noticed that the quality of milk given by his cows varie ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
- POJ 3261 Milk Patterns(后缀数组+单调队列)
题意 找出出现k次的可重叠的最长子串的长度 题解 用后缀数组. 然后求出heigth数组. 跑单调队列就行了.找出每k个数中最小的数的最大值.就是个滑动窗口啊 (不知道为什么有人写二分,其实写啥都差不 ...
- poj 3261 Milk Patterns 后缀数组 + 二分
题目链接 题目描述 给定一个字符串,求至少出现 \(k\) 次的最长重复子串,这 \(k\) 个子串可以重叠. 思路 二分 子串长度,据其将 \(h\) 数组 分组,判断是否存在一组其大小 \(\ge ...
- POJ3261 Milk Patterns —— 后缀数组 出现k次且可重叠的最长子串
题目链接:https://vjudge.net/problem/POJ-3261 Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Tot ...
- POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7586 Accepted: 3448 Cas ...
- POJ 3261 Milk Patterns 【后缀数组 最长可重叠子串】
题目题目:http://poj.org/problem?id=3261 Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Subm ...
- 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: 7938 Accepted: 3598 Cas ...
随机推荐
- LeetCode算法题-Backspace String Compare(Java实现)
这是悦乐书的第327次更新,第350篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第197题(顺位题号是844).给定两个字符串S和T,如果两个字符串都输入到空文本编辑器 ...
- Snow的追寻--线段树维护树的直径
Snow终于得知母亲是谁,他现在要出发寻找母亲.王国中的路由于某种特殊原因,成为了一棵有n个节点的根节点为1的树,但由于"Birds are everywhere.",他得到了种种 ...
- dp基础√
1.重叠子问题 2.能从小问题推到大问题 Dp: 设计状态+状态转移 状态: 1.状态表示: 是对当前子问题的解的局面集合的一种(充分的)描述.(尽量简洁qwq) ◦ 对于状态的表示 ...
- 修改jar包中class文件
某日,想要更改jar包中的某个class文件,有无rar无法解压jar文件,故找到如下方式进行操作 1.解压某个jar包:在需要解压的jar包目录下,打开命令行(cmd),输入如下命令,输入:C:\j ...
- 理解 OutOfMemoryError 异常
OutOfMemoryError 异常应该可以算得上是一个非常棘手的问题.JAVA 的程序员不用像苦逼的 C 语言程序员手动地管理内存,JVM 帮助他们分配内存,释放内存.但是当遇到内存相关的问题,就 ...
- Vue环境搭建和项目创建
目录 vue项目 环境搭建 项目创建 vue项目 环境搭建 node node ~~ python:node是用c++编写用来运行js代码的 npm(cnpm) ~~ pip:npm是一个终端应用商城 ...
- 封装class类--分割类名后
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Linux系统性能测试工具(二)——内存压力测试工具memtester
本文介绍关于Linux系统(适用于centos/ubuntu等)的内存压力测试工具-memtester.内存性能测试工具包括: 内存带宽测试工具——mbw: 内存压力测试工具——memtester: ...
- Linux服务器安装系统之1-LSI阵列卡raid5配置方法
- oracle 主键自增并获取自增id
1 创建表 /*第一步:创建表格*/ create table t_user( id int primary key, --主键,自增长 username varchar(20), password ...