POJ 1743 (后缀数组+不重叠最长重复子串)
题目链接: http://poj.org/problem?id=1743
题目大意:楼教主の男人八题orz。一篇钢琴谱,每个旋律的值都在1~88以内。琴谱的某段会变调,也就是说某段的数可以加减一个旋律范围的值。问这个谱子内最长不重叠的重复部分大小。
解题思路:
网上题解已经泛滥的题。很多细节都被先辈大神总结了。
在当年后缀数组还不是热门的时候,这题确实是神题。
首先对于旋律变调的处理:
比如123,123,ans=3。
变调之后:456,123,ans=0?不ans=3。
所以不能使用旋律的初始值。应该取每个旋律前后的差值,这样就能保证某段无论怎么变调,都和原来一样。
不过这样就变成n-1个旋律,并且ans会-1,可以拿笔算几组看看。
对于取差值后的n-1个旋律,计算SA和LCP。 PS。很多人SA模板都是有问题的,并且推荐自动末尾补0的SA模板,不容易出现问题。
要求不重叠的重复部分大小,这里套用网上被传承N遍的奇葩结论:
将height数组分组,每组内的后缀之间的height都要大于len,如果每组内的后缀之间的最长公共前缀有大于len的而且这两个后缀的SA之差大于len就说明存在长度至少为len的不重复子串。求最长公共前缀就要用到height数组,因为这组中任意两个后缀的公共前缀必定是某些height值中的最小值,而这个值如果最大则一定是这组中height中的最大值。
由于SA数组按字典序来的,二分SA数组长度。如果len符合要求,则先记录。再向右找更大的,否则向左。注意二分的时候ans初始值为0,不然当n=1的时候,等于没有二分就return了一个ans。
#include "cstring"
#include "cstdio"
#include "string"
#include "iostream"
using namespace std;
#define maxn 23000
int n,r[maxn],tmp[maxn];
template <class T>
inline bool read(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return ; //EOF
while(c!='-'&&(c<''||c>'')) c=getchar();
sgn=(c=='-')?-:;
ret=(c=='-')?:(c-'');
while(c=getchar(),c>=''&&c<='') ret=ret*+(c-'');
ret*=sgn;
return ;
}
struct Suffix
{
int sa[maxn],rk[maxn],height[maxn];
int t[maxn],t2[maxn],c[maxn],m;
void init() {m=;}
int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];}
void build()
{
int i,k,p,*x=t,*y=t2;
r[n++]=;
for (i=; i<m; i++) c[i]=;
for (i=; i<n; i++) c[x[i]=r[i]]++;
for (i=; i<m; i++) c[i]+=c[i-];
for (i=n-; i>=; i--) sa[--c[x[i]]]=i;
for (k=,p=; k<n; k*=,m=p)
{
for (p=,i=n-k; i<n; i++) y[p++]=i;
for (i=; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=; i<m; i++) c[i]=;
for (i=; i<n; i++) c[x[y[i]]]++;
for (i=; i<m; i++) c[i]+=c[i-];
for (i=n-; i>=; i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=;
x[sa[]]=;
for (i=; i<n; i++) x[sa[i]]=cmp(y,sa[i-],sa[i],k)?p-:p++;
}
n--;
}
void LCP()
{
int i,j,k=;
for (i=; i<=n; i++) rk[sa[i]]=i;
for (i=; i<n; i++)
{
if (k) k--;
j=sa[rk[i]-];
while (r[i+k]==r[j+k]) k++;
height[rk[i]]=k;
}
}
bool judge(int len)
{
int l=sa[],r=sa[];
for(int i=;i<=n;i++)
{
if(height[i]<len)
{
l=sa[i];r=sa[i];
continue;
}
l=min(l,sa[i]);
r=max(r,sa[i]);
if(r-l>len) return true;
}
return false;
}
int BinarySearch()
{
int l=,r=n,mid,ans=;//注意ans=0,不然当n=1的时候返回的是没赋值的ans
while(l<=r)
{
int mid=l+(r-l)/;
if(judge(mid)) {ans=mid;l=mid+;}
else r=mid-;
}
return ans;
}
};
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
while(read(n)&&n)
{
for(int i=; i<n; i++) read(tmp[i]);
for(int i=; i<n-; i++) {r[i]=tmp[i+]-tmp[i]+;}
Suffix a;
a.init();
a.build();
a.LCP();
int ans=a.BinarySearch();
if(ans<) printf("0\n");
else printf("%d\n",ans+);
}
}
13560509 | neopenx | 1743 | Accepted | 840K | 407MS | C++ | 2761B | 2014-10-24 10:20:38 |
POJ 1743 (后缀数组+不重叠最长重复子串)的更多相关文章
- POJ 1743 后缀数组不重叠最长重复子串
#include<stdio.h> #include<string.h> #include<algorithm> #define maxn 30000 using ...
- [Poj1743] [后缀数组论文例题] Musical Theme [后缀数组不可重叠最长重复子串]
利用后缀数组,先对读入整数处理str[i]=str[i+1]-str[i]+90这样可以避免负数,计算Height数组,二分答案,如果某处H<lim则将H数组分开,最终分成若干块,判断每块中是否 ...
- [poj 3693]后缀数组+出现次数最多的重复子串
题目链接:http://poj.org/problem?id=3693 枚举长度L,看长度为L的子串最多能重复出现几次,首先,能出现1次是肯定的,然后看是否能出现两次及以上.由抽屉原理,这个子串出现次 ...
- POJ 1743 Musical Theme 后缀数组 不可重叠最长反复子串
二分长度k 长度大于等于k的分成一组 每组sa最大的和最小的距离大于k 说明可行 #include <cstdio> #include <cstring> #include & ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- POJ 1743 Musical Theme(不可重叠最长重复子串)
题目链接:http://poj.org/problem?id=1743 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一 ...
- 【poj1743-Musical Theme】不可重叠最长重复子串-后缀数组
http://poj.org/problem?id=1743 这题是一道后缀数组的经典例题:求不可重叠最长重复子串. 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲 ...
- POJ-1743 Musical Theme 字符串问题 不重叠最长重复子串
题目链接:https://cn.vjudge.net/problem/POJ-1743 题意 给一串整数,问最长不可重叠最长重复子串有多长 注意这里匹配的意思是匹配串的所有元素可以减去或者加上某个值 ...
- poj 3261 后缀数组 可重叠的 k 次最长重复子串
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16430 Accepted: 7252 Ca ...
随机推荐
- [COJ0988]WZJ的数据结构(负十二)
[COJ0988]WZJ的数据结构(负十二) 试题描述 输入 见题目,注意本题不能用文件输入输出 输出 见题目,注意本题不能用文件输入输出 输入示例 输出示例 数据规模及约定 1≤N≤1500,M≤N ...
- TCP/IP协议原理【转载】
前述 各种L2数据网具有不同的通信协议与帧结构,其网络节点设备可以是各种类型的数据交换机(X.25.FR.Ethernet和ATM等分组交换机):而L3数据网(IP网或internet) ...
- Dynamo和Bigtable对比
数据结构化问题 首先要提到的是两者存储数据属性上的区别,虽然两者都是以key/value形式进行存储,但Dynamo偏向存储原数据,因为其所存储的数据是非结构化数据,对value的解析完 ...
- Linux MySQL 存储引擎详解
MySQL常用的存储引擎为MyISAM.InnoDB.MEMORY.MERGE,其中InnoDB提供事务安全表,其他存储引擎都是非事务安全表. MyISAM是MySQL的默认存储引擎.MyISAM不支 ...
- 隐藏Nginx/Apache版本号的安全性与方法
一.先介绍nginx隐藏版本号的方法. 搭建好nginx或者apache,为了安全起见我们都会隐藏他们的版本号,这边讲的是nginx的版本号,如果你也想隐藏apache的版本号,那请点前面的链接.请看 ...
- linux 学习一:安装jdk和tomcat
使用secureCRT 一.首先安装centos的rzsz. 1.yum自动安装:(yum安装rzsz) yum install lrzsz 2.手动安装方法如下:(包有问题,还是采用第一种方式) 2 ...
- 【转】实战 SSH 端口转发
本文转自:http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/index.html,至于有什么用,懂的懂! 实战 SSH 端口转发 通 ...
- Delphi经验总结(1)
先人的DELPHI基础开发技巧 ◇[DELPHI]网络邻居复制文件 uses shellapi; copyfile(pchar('newfile.txt'),pchar('//computername ...
- MFC 密码框
使用Edit Control 在属性面板中,设置“行为”为password
- HTML5学习记录1-新特性
新特性 HTML5 中的一些有趣的新特性: 1. 用于绘画的 canvas 元素 2. 用于媒介回放的 video 和 audio 元素 3. 对本地离线存储的更好的支持 4. 新的特殊内容元素,比如 ...