题目链接

题意:给定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. Hibernate基本CRUD

    1 hibernate 框架介绍 冬眠:开发的代码基本不变. 1.1回顾jdbc Java提供的标准的数据访问的API 作用:完成应用程序java程序中的数据和db中的数据进行交换. 工作过程: A ...

  2. 如何在MyEclipse中通过hibernate使用jtds驱动连接数据库,并向数据库添加数据的方法

    最近学习了下如何在MyEclipse中通过hibernate使用jtds驱动连接数据库,并向数据库添加数据的方法,虽然MyEclipse中自带了连接数据库的方法,我也尝试了下其他方法,如有不当之处请指 ...

  3. Android笔记:限定符

    屏幕特征限定符描述大小 small 提供给小屏幕设备的资源 normal 提供给中等屏幕设备的资源 large 提供给大屏幕设备的资源 xlarge 提供给超大屏幕设备的资源分辨率 ldpi 提供给低 ...

  4. mongodb配置文件.conf

    启动方式 ./bin/mongod -f MongoDB.conf 会看到 about to fork child process, waiting until server is ready for ...

  5. Mac 下查看 Android Studio 的 SHA1的方法

    cmd -> ->cd .android ->keytool -v -list -keystore debug.keystore 默认口令:android ************* ...

  6. 解决Fragment在Viepager中切换不保存状态的问题

    在FragmentPagerAdapter中重写以下方法: @Override public Object instantiateItem(ViewGroup container, int posit ...

  7. NYOJ题目1162数字

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAr8AAAJ/CAIAAAD+kywNAAAgAElEQVR4nO3dO1LjzN4H4G8T5CyE2A ...

  8. Lattice 的 Framebuffer IP核使用调试笔记之IP核生成与参数设置

    本文由远航路上ing 原创,转载请标明出处. 这节笔记记录IP核的生成以及参数设置. 先再IP库里下载安装Framebuffer 的ipcore 并安装完毕. 一.IP核的生成: 1.先点击IP核则右 ...

  9. mysql扩展库-1

    启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...

  10. Python中带参装饰器理解