题目大概是给n个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等。

这题是传说中楼教主男人八题之一,虽然已经是用后缀数组解决不可重叠最长重复子串的经典题了。。但其实没那么简单,题目数据不强,网上一些代码都是不正确的。

  • 首先把问题转化成重复子串的问题:把原串每一位都与前一位相减。这样得出的新串如果有两个长度为n的子串相同,那么它们对应在原串的长度n+1的子串也就相似。
  • 所以接下来要求的就是这个新串不可“重叠”最长重复子串——问题就在这儿,这不只是要求不可重叠,还要求两个子串要隔至少一个位置,因为如果两个子串靠在一起这样反应到原串那两个子串各自的首尾是重合的。

比如数据:9  1 1 1 1 1 1 1 1 1

隔至少一个位置其实只要原本的if(mx-mm>=k)改成if(mx-mm>k)就行了。

最后大概描述一下不可重叠最长重复子串的解法:

  • O(logn)二分枚举子串长度,判断解是否成立
  • O(n)判断长度是否成立:把互相之间LCP大于等于长度的分为一组,这通过个扫一遍height即可,因为后缀是有序的,相邻的后缀间的LCP必定的极大的;接下来就找到每个组里后缀sa值最大和最小的,如果差值大于(等于)k就成立,因为这样小下标的后缀沿着LCP下去走k步才不会盖到大下标的后缀。

另外,说一下二分枚举解,二分具体写法很多吧,也不知道正不正确。。我那样的写法我发现:

  • 如果是求最小解,mid要取floor,即mid=(left+right)/2
  • 如果是求最大解,mid要取ceil,即mid=(left+right+1)/2

看起来好像是这个样子的。。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 22222
#define INF (1<<30)
int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
int sa[MAXN],rank[MAXN],height[MAXN];
void SA(int *r,int n,int m){
int *x=wa,*y=wb; for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[x[i]=r[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[x[i]]]=i; int p=;
for(int j=; p<n; j<<=,m=p){
p=;
for(int i=n-j; i<n; ++i) y[p++]=i;
for(int i=; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
for(int i=; i<n; ++i) wv[i]=x[y[i]];
for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[wv[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[wv[i]]]=y[i];
swap(x,y); x[sa[]]=; p=;
for(int i=; i<n; ++i) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
} for(int i=; i<n; ++i) rank[sa[i]]=i;
int k=;
for(int i=; i<n-; height[rank[i++]]=k){
if(k) --k;
for(int j=sa[rank[i]-]; r[i+k]==r[j+k]; ++k);
}
} int n,a[MAXN],r[MAXN];
bool isok(int k){
bool flag=;
int mx=-INF,mm=INF;
for(int i=; i<=n; ++i){
if(height[i]>=k){
mm=min(mm,min(sa[i],sa[i-]));
mx=max(mx,max(sa[i],sa[i-]));
if(mx-mm>k) return ;
}else{
mx=-INF,mm=INF;
}
}
return ;
}
int main(){
while(~scanf("%d",&n) && n){
for(int i=; i<n; ++i) scanf("%d",a+i);
--n;
for(int i=; i<n; ++i) r[i]=a[i+]-a[i]+;
r[n]=;
SA(r,n+,);
int l=,r=n>>;
while(l<r){
int mid=l+r+>>;
if(isok(mid)) l=mid;
else r=mid-;
}
if(l>=) printf("%d\n",l+);
else printf("%d\n",);
}
return ;
}

POJ1743 Musical Theme(二分+后缀数组)的更多相关文章

  1. POJ-1743 Musical Theme,后缀数组+二分!

                                                        Musical Theme 人生第一道后缀数组的题,采用大众化思想姿势极其猥琐. 题意:给你n个 ...

  2. poj1743 Musical Theme【后缀数组】【二分】

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 35044   Accepted: 11628 D ...

  3. POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串

    A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...

  4. POJ 1743 Musical Theme 二分+后缀数组

    Musical Theme   Description A musical melody is represented as a sequence of N (1<=N<=20000)no ...

  5. poj1743 Musical Theme(后缀数组|后缀自动机)

      [题目链接] http://poj.org/problem?id=1743     [题意]     求不可重叠最长重复子串.   2015-11-27 [思路] 1)      据题意处理字符串 ...

  6. 【POJ1743】Musical Theme(后缀数组)

    [POJ1743]Musical Theme(后缀数组) 题面 洛谷,这题是弱化版的,\(O(n^2)dp\)能过 hihoCoder 有一点点区别 POJ 多组数据 题解 要求的是最长不可重叠重复子 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 使用jmeter+ant进行接口自动化测试(数据驱动)之一:设计jmeter脚本

    最近在做接口测试,因为公司有使用jmeter做接口测试的相关培训资料,所以还是先选择使用jmeter来批量管理接口,进行自动化测试.话不多说,进入正题: 1.使用csv文件保存接口测试用例,方便后期对 ...

  2. mysql数据库导入sql文件时提示“Error Code: 1153 - Got a packet bigger than 'max_allowed_packet' bytes”解决办法

    向mysql数据库中导入sql文件时,如果文件过大(几百M),会提示"Error Code: 1153 - Got a packet bigger than 'max_allowed_pac ...

  3. 听翁恺老师mooc笔记(13)--类型定义和联合

    typedef 虽然我们知道使用struct这个关键字定义一个结构类型,然后可以使用该结构类型定义变量.但是每次要使用的时候都需要带着struct这个关键字,那么如何摆脱这个关键字哪?C语言提供了一个 ...

  4. Alpha冲刺No.9

    一.站立式会议 继续解决真实手机中的问题,如果不能解决,请教助教学姐 数据库备忘录的获取和上传 细化界面设计 二.项目实际进展 用一种奇怪的方式解决了真实手机中的问题,在总结里细说. 完成数据库备忘录 ...

  5. win7如何以管理员身份运行命令提示符(cmd)

    1.进入到: C:\Windows\System32 2.找到cmd.exe文件 3.右键单击 ,选择 以管理员身份运行.

  6. js:防抖动与节流

    http://blog.csdn.net/crystal6918/article/details/62236730

  7. DNS搜索过程

    以www.renyi.com为例 一:客户端首先检查本地HOST文件,是否有对应的IP地址,如果有,客户端直接访问,如果没有,则执行下一步. 二:客户端查看本地缓存信息,是否有对应的IP地址,如果有, ...

  8. Full-Stack-Fundation-Udacity------Lesson 1 Working with CRUD

    因为手头在做一个项目,我负责后台,就顺带快进学习Udacity上一个水课(?):Full Stack Foundation.上课的好像是个印度小哥(?),按1.5倍速听讲话还是有点逗的.废话不多说,进 ...

  9. maven入门(1-3)maven的生命周期

      maven的生命周期 maven的生命周期是抽象的,其实际行为都由插件来完成,引入maven 的 生命周期就是为了对所有的构建过程进行抽象和统一. 这种方式类似于模板方法,模板方法模式在父类中定义 ...

  10. 丢掉DDL,我用这招3分钟清空 MySQL 9亿记录数据表

    摘要:最近由于福建开机广告生产环境的广告日志备份表主键(int类型)达到上限(21亿多),不能再写入数据,需要重新清空下该表并将主键重置,但由于表里有8亿多记录的数据量,使用重置命令及DDL命令执行地 ...