这也是一道例题

给定一个字符串,求至少出现 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 次最长重复子串【后缀数组】的更多相关文章

  1. POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7586   Accepted: 3448 Cas ...

  2. 【POJ 3261】Milk Patterns 可重叠的k次最长重复子串

    可重叠的k次最长重复子串 #include<cstdio> #include<cstring> #include<algorithm> using namespac ...

  3. poj 3261 后缀数组 可重叠的 k 次最长重复子串

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16430   Accepted: 7252 Ca ...

  4. poj 3261 求可重叠的k次最长重复子串

    题意:求可重叠的k次最长重复子串的长度 链接:点我 和poj1743差不多 #include<cstdio> #include<iostream> #include<al ...

  5. 后缀数组练习2:可重叠的k次最长重复子串

    其实和上一题是差不多的,只是在二分check的时候有一些小小的改动 1468: 后缀数组2:可重叠的k次最长重复子串 poj3261 时间限制: 1 Sec  内存限制: 128 MB提交: 113  ...

  6. poj 1743 Musical Theme(最长重复子串 后缀数组)

    poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...

  7. 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组

    http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...

  8. poj3261 Milk Patterns 后缀数组求可重叠的k次最长重复子串

    题目链接:http://poj.org/problem?id=3261 思路: 后缀数组的很好的一道入门题目 先利用模板求出sa数组和height数组 然后二分答案(即对于可能出现的重复长度进行二分) ...

  9. POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16742   Accepted: 7390 Ca ...

随机推荐

  1. FPGA中改善时序性能的方法_advanced FPGA design

    本文内容摘自<advanced FPGA design>对应中文版是 <高级FPGA设计,结构,实现,和优化>第一章中的内容 FPGA中改善时序,我相信也是大家最关心的话题之一 ...

  2. VB6.0快捷键大全(转)

    窗体设置,控件布局时用: alt+v+x可以快速显示出工具框 Alt+P+N 引用 ctrl+左右键头可以移动控件 shift+左右键头调整控件大小 F7   切换到编辑窗口 Shift+f7 切换代 ...

  3. Docker学习总结之Run命令介绍

    Docker学习总结之Run命令介绍 本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 在使用Docker时,执行最多的命令某 ...

  4. 程序员眼中的UML

    --克服用例图的恐惧 在实际工作中,大部分程序员很少接触到需求分析,即使有需求分析,也是草草了事,没有用正规的方式来表达,所以一般程序员使用用例图的机会是不多的.但是却又常常在各种媒体上看见用例图,于 ...

  5. 3027 - Corporative Network(并差集)

    3027 - Corporative Network A very big corporation is developing its corporative network. In the begi ...

  6. D - 楼下水题(kmp+Manacher)

    D - 楼下水题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Statu ...

  7. CSS中 清除浮动解决“包含问题”

    今天看到大神对浮动定位作了个详细的分析  刚好就分析了当时任务三遇到的问题 在一个div中定义了三个div,让横向排列,结果父元素div的背景色显示不出来了 ,这是个经典问题----包含浮动 < ...

  8. javasrcipt日期一些方法和格式转化

    Js获取当前日期时间及其它操作 var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();   ...

  9. 使用超链接跳转页面(GridView)

    1. the html markup <div> <asp:GridView ID=" OnPageIndexChanging="GridView1_PageIn ...

  10. 解决 win10 预览版开始菜单打不开的问题

    除了该文章[http://jingyan.baidu.com/article/64d05a025d2668de55f73b9e.html]里面说的解决方法之外,我只加上一点 . 打开本机防火墙,或者调 ...