POJ 3261 可重叠k次最长重复子串
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 13127 | Accepted: 5842 | |
Case Time Limit: 2000MS |
Description
Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.
To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.
Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.
Input
Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.
Output
/*
POJ 3261 可重叠k次最长重复子串 给你一串数字,求其中出现k次的最长子串 最开始想的是二分最长长度,然后判断一下是否有k个子串
但是在判断的时候2b了,并没有判断它们是否是同一个子串,于是乎
应该进行分组讨论,因为是height中存的是排过序后的最长前缀
假设height[] = 0 0 1 4 4 4 3 2 4 4
只有前3个4是同一个子串(排序后一段连续子串是相似的) 所以成了找出height连续大于等于mid的长度sum,判断sum+1是否>=k hhh-2016-03-11 21:29:00
*/
#include <algorithm>
#include <cmath>
#include <queue>
#include <iostream>
#include <cstring>
#include <map>
#include <cstdio>
#include <vector>
#include <functional>
#define lson (i<<1)
#define rson ((i<<1)|1)
using namespace std;
typedef long long ll;
const int maxn = 100050; int t1[maxn],t2[maxn],c[maxn];
bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] &&r[l+a] == r[l+b];
} void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
{
n++;
int p,*x=t1,*y=t2;
for(int i = 0; i < m; i++) c[i] = 0;
for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
for(int i = 1; i < m; i++) c[i] += c[i-1];
for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
for(int j = 1; j <= n; j <<= 1)
{
p = 0;
for(int i = n-j; i < n; i++) y[p++] = i;
for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
for(int i = 0; i < m; i++) c[i] = 0;
for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
for(int i = 1; i < m; i++) c[i] += c[i-1];
for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x,y);
p = 1;
x[sa[0]] = 0;
for(int i = 1; i < n; i++)
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
if(p >= n) break;
m = p;
}
int k = 0;
n--;
for(int i = 0; i <= n; i++)
Rank[sa[i]] = i;
for(int i = 0; i < n; i++)
{
if(k) k--;
int j = sa[Rank[i]-1];
while(str[i+k] == str[j+k]) k++;
height[Rank[i]] = k;
}
} int Rank[maxn],height[maxn];
int sa[maxn],str[maxn];
int a[maxn];
int n; bool judge(int ans,int k)
{
int i =2;
while(1)
{
while(height[i] < ans && i <= n) i++;
int num = 0;
if(i > n) break;
while(height[i] >= ans && i <= n){num++;i++;}
if(num+1 >= k)return 1;
}
return 0;
}
map<int,int> mp;
int main()
{
int k,cas = 1;
while(scanf("%d%d",&n,&k) != EOF)
{
int tot = 1,x;
mp.clear();
for(int i = 0; i < n; i++)
{
scanf("%d",&x);
if(!mp[x])
mp[x] = tot++;
a[i] = mp[x];
}
a[n] = 0; get_sa(a,sa,Rank,height,n,n+1);
int ans = 0;
int l=1,r=n;
// for(int i =2;i <= n;i++)
// printf("%d %d\n",sa[i],height[i]);
// cout <<endl;
while(l <= r)
{
int mid = (l+r)>>1;
if(judge(mid,k))
{
ans = mid;
l = mid + 1;
}
else
r = mid-1;
}
printf("%d\n",ans);
}
return 0;
}
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 3261 可重叠的 k 次最长重复子串【后缀数组】
这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...
- POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16742 Accepted: 7390 Ca ...
- poj3261 Milk Patterns 后缀数组求可重叠的k次最长重复子串
题目链接:http://poj.org/problem?id=3261 思路: 后缀数组的很好的一道入门题目 先利用模板求出sa数组和height数组 然后二分答案(即对于可能出现的重复长度进行二分) ...
- 后缀数组--可重叠的K次最长重复子串(POJ3261)
题目:Milk Patterns #include <stdio.h> #include <string.h> #define N 1000010 int wa[N],wb[N ...
随机推荐
- [知识梳理]课本3&9.1
函数:关键词:参数.返回值.函数返回类型.函数体. 函数按照返回类型,可以分为有参函数和无参函数. 函数根据是否有返回值,可以分为返回值函数和非返回值函数. 函数的定义:函数的定义可以放在任意 ...
- Mongodb中 Documents文档说明
mongodb使用BSON格式存储数据记录. 如下图: 文档结构 文档有键值对组成, 有以下结构: { field1: value1, field2: value2, ... ...
- Ajax 的onreadystatechange事件注意事项.
<script type="text/javascript"> function createXHR() { var request = false; try { re ...
- linux查看文件内容的常见命令
1.cat命令,显示文件的所有内容,内容过多则显示最后一屏一般用于内容较少文件 2.more命令,分页显示文件的内容一般用于文件内容过多的文件,回车显示下一行,空格显示下一页,q/Q退出 3.head ...
- 新概念英语(1-41)Penny's bag
新概念英语(1-41)Penny's bag Who is the tin of tobacco for? A:Is that bag heavy, Penny? B:Not very. A:Here ...
- 运维-替换kibana徽标
作为一名纯运维人员,想更改kibana的徽标. 并不能像开发一样去看源码并修改源码. 所以我们可以替换徽标. 先来一个效果图.我的版本是5.5.1. 具体的修改过程: 在kibana安装路径下面. o ...
- SpringBoot使用log4j
1.添加log4j相关依赖 在pom.xml文件中添加相关依赖: <!--配置log4j--> <dependency> <groupId>org.springfr ...
- 浅谈 DML、DDL、DCL的区别
一.DML DML(data manipulation language)数据操纵语言: 就是我们最经常用到的 SELECT.UPDATE.INSERT.DELETE. 主要用来对数据库的数据进行一些 ...
- SpringMVC(六):@RequestMapping下使用@RequestHeader绑定请求报头的属性值、@CookieValue绑定请求中的Cookie值
备注:我本地浏览器的报头(Request Header)信息如下: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image ...
- Hive:表1inner join表2结果group by优化
问题背景 最近遇到一个比较棘手的事情:hive sql优化: lib表(id,h,soj,noj,sp,np) --一个字典表 mitem表(md,mt,soj,noj,sp,np)- ...