题目链接

题意:给定n个数字,求超过5个数字的,最长的,变化相同的,不相交的重复子串

分析:男人8题中的一题!数列相邻两项做差,形成新数列,即求数列中的最长重复子串(不可相交)。

后缀数组+二分答案。假如二分得到答案L,如何知道它是可行的呢? 因为对于排序后的后缀,Lcp ( Suffix ( List [ i ] ) , Suffix ( List [ i - 1 ] ) ) 是所有与Suffix ( List [ i ] )的LCP值中最大的一个。 因为 Height [ i ] 表示的是排序后后缀数组中第i个后缀和第i-1个后缀的LCP值。 那么对于后缀数组中的一段 L - R , 若 Height [ L + 1 ] ~ Height [ R ] 全部大于等于L,那么就等价于第L到第R个后缀中任意两个后缀的LCP值都大于等于L。 那么只要取这里面相隔最远的两个后缀,若他们相距大于L,那么就是可行的。 ( 为什么不是等于L呢 ? 因为我们取的关键字是 S[i]-S[i-1] , 若相距等于L,那么两段里面的首尾相连了,是不符合条件的)

简单来说,先对height数组分段,然后看每段是否有满足题意的子串。

#include <cstdio>
#include <cstring>
#include <algorithm> const int N = 2e4 + 5;
int sa[N], rank[N], height[N];
int t[N], t2[N], c[N];
int a[N]; void da(int *s, int n, int m = 128) {
int i, p, *x = t, *y = t2;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[i]=s[i]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
for (int k=1; k<=n; k<<=1) {
for (p=0, i=n-k; i<n; ++i) y[p++] = i;
for (i=0; i<n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[y[i]]]++;
for (i=0; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
std::swap (x, y);
p = 1; x[sa[0]] = 0;
for (i=1; i<n; ++i) {
x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p - 1 : p++);
}
if (p >= n) break;
m = p;
}
} void calc_height(int n) {
int i, k = 0;
for (i=0; i<n; ++i) rank[sa[i]] = i;
for (i=0; i<n; ++i) {
if (k) k--;
int j = sa[rank[i]-1];
while (a[i+k] == a[j+k]) k++;
height[rank[i]] = k;
}
} int n; bool check(int m) {
int mn = sa[0], mx = sa[0];
for (int i=1; i<n; ++i) {
if (height[i] >= m) {
mn = std::min (mn, std::min (sa[i], sa[i-1]));
mx = std::max (mx, std::max (sa[i], sa[i-1]));
if (mn + m < mx) {
return true;
}
} else {
mn = mx = sa[i];
}
}
return false;
} int main() {
while (scanf ("%d", &n) == 1) {
if (!n) break;
for (int i=0; i<n; ++i) {
scanf ("%d", a+i);
if (i) a[i-1] = a[i] - a[i-1] + 100; //做差后有负数,+100保证为正数
} if (n <= 10) {
puts ("0");
continue;
} a[n-1] = 0;
da (a, n, 200);
calc_height (n); int ans = 0;
int left = 0, right = n;
while (left <= right) {
int mid = left + right >> 1;
if (check (mid)) {
ans = std::max (ans, mid);
left = mid + 1;
} else {
right = mid - 1;
}
} if (ans >= 4) {
printf ("%d\n", ans + 1);
} else {
puts ("0");
}
}
return 0;
}

  

后缀数组 POJ 1743 Musical Theme的更多相关文章

  1. POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)

    永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...

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

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

  3. Poj 1743 Musical Theme (后缀数组+二分)

    题目链接: Poj  1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...

  4. POJ 1743 Musical Theme 【后缀数组 最长不重叠子串】

    题目冲鸭:http://poj.org/problem?id=1743 Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Su ...

  5. POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

    Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...

  6. poj 1743 Musical Theme (后缀数组+二分法)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16162   Accepted: 5577 De ...

  7. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  8. POJ 1743 Musical Theme(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1743 [题目大意] 给出一首曲子的曲谱,上面的音符用不大于88的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, ...

  9. [poj 1743] Musical Theme 后缀数组 or hash

    Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...

随机推荐

  1. August 9th 2016, Week 33rd Tuesday

    Tomorrow is never clear, our time is here. 明天是未知的,我们还是要过好当下. Tomorrow is not unpredictable, it is cl ...

  2. 51nod1019逆序数(归并排序/树状数组)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1019 题意:中文题诶- 思路: 方法1:归并排序- 归并排序过 ...

  3. [转]DB2类型转换函数

    Src URL:http://www.cnblogs.com/QQParadise/articles/2642677.html

  4. 第一课 移动端&响应式

    一.调试工具介绍(Chrome Emulation) 1.Device(设备相关) 自定义尺寸.Network(网络模拟).UseAgent(浏览器信息).缩放 2.Media(媒体) 3.Netwo ...

  5. windows服务 - C# U盘升级

    1.左侧工具栏里有Timer控件,但是如果调用的是系统时间,就需要添加System.timer.timer空间下的控件.   2.服务编写之后,还不能由SCM(服务控制管理器)进行管理,需要给该服务添 ...

  6. EF – 6.一对一关联

    5.6.6 <一对一关联概述>  5.6.7 <一对一关联CRUD演示>  在两讲视频中,首先介绍了数据库中一对一关联表的设计规范,接着通过实例介绍了如何合适Entity Fr ...

  7. asmlinkage

    转自:http://www.cnblogs.com/china_blue/archive/2010/01/15/1648523.html 声明,仅为了便于自己记忆和查询,非原创,摘自:http://b ...

  8. Android中Service 使用详解(LocalService + RemoteService)

    Service 简介: Service分为本地服务(LocalService)和远程服务(RemoteService): 1.本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外L ...

  9. 【翻译一】java-并发

    Lesson: Concurrency Computer users take it for granted that their systems can do more than one thing ...

  10. android 入门-Service

    sdk 1.7 package com.example.hellowrold; import java.util.Random; import com.example.hellowrold.R.id; ...