[poj 1743]差分+后缀数组
题目链接: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]差分+后缀数组的更多相关文章
- Musical Theme POJ - 1743(后缀数组+二分)
求不可重叠最长重复子串 对于height[i]定义为sa[i]和 sa[i-1]的最长公共前缀 这个最长公共前缀的值肯定是最大的 证明: 设rank[j] < rank[k], 则不难证明后缀j ...
- POJ 1743-POJ - 3261~后缀数组关于最长字串问题
POJ 1743 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1~~88范围内的整数,现在要找一个重复的主题.“主题”是整个音符序列的一个子串,它需 ...
- POJ 2406 KMP/后缀数组
题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...
- P2743(poj1743) Musical Themes[差分+后缀数组]
P2743 乐曲主题Musical Themes(poj1743) 然后呢这题思路其实还是蛮简单的,只是细节特别多比较恶心,忘记了差分带来的若干疏漏.因为转调的话要保证找到相同主题,只要保证一段内相对 ...
- POJ - 1226 Substrings (后缀数组)
传送门:POJ - 1226 这个题跟POJ - 3294 和POJ - 3450 都是一样的思路,一种题型. POJ - 3294的题解可以见:https://www.cnblogs.com/li ...
- POJ 2217 Secretary (后缀数组)
标题效果: 计算两个公共串串最长的字符串的长度. IDEAS: 这两个组合的字符串. 然后直接确定运行后缀数组height 然后,你可以直接扫描一次height .加个是不是在一个串中的推断就能够了. ...
- 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 ...
- Milk Patterns POJ - 3261(后缀数组+二分)
题意: 求可重叠的最长重复子串,但有一个限制条件..要至少重复k次 解析: 二分枚举k,对于连续的height 如果height[i] >= k 说明它们至少有k个元素是重复的,所以判断一下就好 ...
- POJ 3581 Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
随机推荐
- Python学习笔记:第一天python基础
目录 1. python简介 2. python的安装 3. 编写第一个helloword 4. 变量和常量 5. 数据类型 6. 输入 7. if语句 1. python简介 python是在198 ...
- [Cracking the Coding Interview] 4.5 Validate BST
Implement a function to check if a binary tree is a binary search tree. 这道题很经典,让我们判断一棵树是不是二叉查找树.但是首先 ...
- 【转】Android开发之ListView+EditText-要命的焦点和软键盘问题解决办法
Android开发之ListView+EditText-要命的焦点和软键盘问题解决办法 [原文链接] 这篇文章完美的解决了我几个月没结论的bug... 感谢热爱分享的技术达人~ 我是怎么走进这个大坑的 ...
- ThinkPhP html原样入库
开始正式搞php,在配置好PHP环境之后,从学习thinkphp框架开始php之旅. 在实际项目中需要将一个网页的html保存到数据库中,但不能被转义.由于thinkphp的数据库操作为通过他们自己O ...
- Android开发——Google关于Application Not Responding的建议
秒内没有执行完毕. 2. 避免ANR的一些建议 Android applications normally run entirely on asingle (i.e. main) thre ...
- Eclipse 导入项目与 svn 插件关联全过程记录
文章摘自:http://www.cnblogs.com/xmmcn/archive/2013/03/01/2938365.html 感谢博友分享! Eclipse 导入项目与 svn 插件关联全过程记 ...
- malloc函数分配失败处理的严重性
本次在实际测试情况下,发现程序无缘无故的异常,导致看门狗超时复位,经过排查是malloc函数分配失败的时候,依然对指针进行了操作,导致异常.以前没重视这个问题是因为,总觉的malloc基本都会成功的, ...
- (原)一段看似美丽的for循环,背后又隐藏着什么
之前很长一段时间,潜心修炼汇编,专门装了一个dos7,慢慢玩到win32汇编,再到linux的AT&A汇编,尝试写mbr的时候期间好几次把centos弄的开不了机,又莫名其妙的修好了,如今最大 ...
- css的水平居中和垂直居中总结
Html代码: <div class="md-warp"> <div class="md-main">块级元素</div> ...
- popen和system问题
popen和system问题 1. 问题描述 C的代码里面去调用命令启动一个shell脚本,分别使用了下面两个途径. 其中一个是: func1(cmd) { popen(cmd,type); pclo ...