题目链接:http://poj.org/problem?id=1743

首先,musical theme只与前后位置的增减关系有关,而与绝对的数值无关,因此想到做一次差分。

然后对于差分后的数组,找到最长的出现两次(或两次以上)的一个子串即可。这个如果说两个子串可以交叉的话就好做了,直接取height的最大值即可,但是题目要求不能交叉,前几天一位师兄讲课刚讲了,可以用二分做。对于一个指定长度L,判断它是否可行,就用这个L去划分height数组,对于每个部分的分别看看最远的两个是否没有交叉就可以了。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; const int maxn=; #define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[maxn*],wb[maxn*],wv[maxn*],wss[maxn*];
int c0(int *r,int a,int b)
{
return r[a]==r[b] && r[a+]==r[b+] && r[a+]==r[b+];
}
int c12(int k,int *r,int a,int b)
{
if (k==) return r[a]<r[b] || (r[a]==r[b]&&c12(,r,a+,b+));
else return r[a]<r[b] || (r[a]==r[b]&&wv[a+]<wv[b+]);
}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for (i=;i<n;i++) wv[i]=r[a[i]];
for (i=;i<m;i++) wss[i]=;
for (i=;i<n;i++) wss[wv[i]]++;
for (i=;i<m;i++) wss[i]+=wss[i-];
for (i=n-;i>=;i--) b[--wss[wv[i]]]=a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn=r+n;
int *san=sa+n,ta=,tb=(n+)/,tbc=,p;
r[n]=r[n+]=;
for (i=;i<n;i++) if (i%!=) wa[tbc++]=i;
sort(r+,wa,wb,tbc,m);
sort(r+,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for (p=,rn[F(wb[])]=,i=;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-],wb[i])?p-:p++;
if (p<tbc) dc3(rn,san,tbc,p);
else for (i=;i<tbc;i++) san[rn[i]]=i;
for (i=;i<tbc;i++) if (san[i]<tb) wb[ta++]=san[i]*;
if (n%==) wb[ta++]=n-;
sort(r,wb,wa,ta,m);
for (i=;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for (i=,j=,p=;i<ta&&j<tbc;p++)
sa[p]=c12(wb[j]%,r,wa[i],wb[j])?wa[i++]:wb[j++];
for (;i<ta;p++) sa[p]=wa[i++];
for (;j<tbc;p++) sa[p]=wb[j++];
}
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
for (int i=n;i<n*;i++)
str[i]=;
dc3(str,sa,n+,m);
int i,j,k=;
for (i=;i<=n;i++) rank[sa[i]]=i;
for (i=;i<n;i++)
{
if (k) k--;
j=sa[rank[i]-];
while (str[i+k]==str[j+k]) k++;
height[rank[i]]=k;
}
}
int a[maxn*];
int ra[maxn*],height[maxn*],sa[maxn*];
bool xk[maxn];
const int INF=0x3f3f3f3f; bool check(int k,int n)
{
for (int i=;i<=n-;i++)
if (height[i]<k) xk[i]=false;
else xk[i]=true;
xk[n]=false;
int left=INF,right=;
for (int i=;i<=n;i++)
{
if (!xk[i])
{
if (right-left>k) return true;
left=INF;
right=;
}
else
{
int zb1=sa[i-];
int zb2=sa[i];
if (zb1<left) left=zb1;
if (zb2<left) left=zb2;
if (zb1>right) right=zb1;
if (zb2>right) right=zb2;
}
}
return false;
} int solve(int n)
{
// a[0..n-2]
// ra[0..n-2]
// sa[1..n-1]
// height[2..n-1]
int l=,r=n-;
while (l<r)
{
int mid=(l+r+)/;
if (check(mid,n)) l=mid;
else r=mid-;
}
// return l;
if (l<) return ;
return l+;
} int main()
{
int n;
while (~scanf("%d",&n) && n)
{
for (int i=;i<n;i++) scanf("%d",&a[i]);
for (int i=;i<n-;i++) a[i]=a[i+]-a[i]+;
// for (int i=0;i<n-1;i++) printf("%d ",a[i]);
// printf("\n");
da(a,sa,ra,height,n-,);
printf("%d\n",solve(n));
}
return ;
}

[poj 1743]差分+后缀数组的更多相关文章

  1. Musical Theme POJ - 1743(后缀数组+二分)

    求不可重叠最长重复子串 对于height[i]定义为sa[i]和 sa[i-1]的最长公共前缀 这个最长公共前缀的值肯定是最大的 证明: 设rank[j] < rank[k], 则不难证明后缀j ...

  2. POJ 1743-POJ - 3261~后缀数组关于最长字串问题

    POJ 1743 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1~~88范围内的整数,现在要找一个重复的主题.“主题”是整个音符序列的一个子串,它需 ...

  3. POJ 2406 KMP/后缀数组

    题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...

  4. P2743(poj1743) Musical Themes[差分+后缀数组]

    P2743 乐曲主题Musical Themes(poj1743) 然后呢这题思路其实还是蛮简单的,只是细节特别多比较恶心,忘记了差分带来的若干疏漏.因为转调的话要保证找到相同主题,只要保证一段内相对 ...

  5. POJ - 1226 Substrings (后缀数组)

    传送门:POJ - 1226 这个题跟POJ - 3294  和POJ - 3450 都是一样的思路,一种题型. POJ - 3294的题解可以见:https://www.cnblogs.com/li ...

  6. POJ 2217 Secretary (后缀数组)

    标题效果: 计算两个公共串串最长的字符串的长度. IDEAS: 这两个组合的字符串. 然后直接确定运行后缀数组height 然后,你可以直接扫描一次height .加个是不是在一个串中的推断就能够了. ...

  7. Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)

    The repetition number of a string is defined as the maximum number \(R\) such that the string can be ...

  8. Milk Patterns POJ - 3261(后缀数组+二分)

    题意: 求可重叠的最长重复子串,但有一个限制条件..要至少重复k次 解析: 二分枚举k,对于连续的height 如果height[i] >= k 说明它们至少有k个元素是重复的,所以判断一下就好 ...

  9. POJ 3581 Sequence(后缀数组)

    Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An,  you are to ...

随机推荐

  1. struts2架构网站漏洞修复详情与利用漏洞修复方案

    struts2从开发出来到现在,很多互联网企业,公司,平台都在使用apache struts2系统来开发网站,以及应用系统,这几年来因为使用较多,被攻击者挖掘出来的struts2漏洞也越来越,从最一开 ...

  2. HDU暑假多校第三场H.Monster Hunter

    一.题意 给定一个树状地图,每个树节点上有一只怪物,打死一只怪物的过程中将会消耗A点HP,打死之后将会获得B点HP.因为树状结构,所以每只怪物必须先打死父节点的怪兽之后在打死子节点的怪物.现在,给定每 ...

  3. linux io 学习笔记(02)---条件变量,管道,信号

    条件变量的工作原理:对当前不访问共享资源的任务,直接执行睡眠处理,如果此时需要某个任务访问资源,直接将该任务唤醒.条件变量类似异步通信,操作的核心:睡眠.唤醒. 1.pthread_cond_t  定 ...

  4. 利用JS调取电脑摄像头,实现拍照功能

    1.调取电脑摄像头非常简单,看代码一幕了然 window.addEventListener("DOMContentLoaded", function() { var canvas ...

  5. BLE(Bluetooth Low Energy)---first part

    原文地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#terms (本人是技术宅,翻译时候,只要 ...

  6. C# List集合去重操作注意点

    今天调试代码时发现list的distinct方法在对引用类型操作时并没有去重,后来查阅资料发现list去重操作对象集合时比较的是对象的一个个引用地址, 因为集合里的对象都是一个个单独的实例,所以并不会 ...

  7. ExtJs工具篇(2)——Aptana Studio 3 汉化

    本身用的是中文版本的,但是输入一些中文后,竟然有乱码,所以就想把它汉化.在网上搜索了一下,把步骤记录如下: 首先到这个网站去 http://aptana.com/support 选择View Docu ...

  8. c#一些常用的方法集合

    是从一个asp.net mvc的项目里看到的.挺实用的. 通过身份证号码获取出生日期和性别 通过身份证号码获取出生日期和性别 #region 由身份证获得出生日期 public static stri ...

  9. 什么鬼,又不知道怎么命名class了

    什么鬼,又不知道怎么命名class了 2015/10/25 · CSS · class 分享到:5 原文出处: 结一(@结一w3cplus)    相信写css的人都会遇到下面的问题: 糟糕,怎么命名 ...

  10. 「赛后补题」HBCPC2018题目代码与思路简析

    这次比赛(2018年第二届河北省大学生程序设计竞赛)虽然没有打,但是题目还是要写的.未完成的题目(还差比较硬核的四题)和思路分析会陆续更新完. Problem A 2011 Mex Query /* ...