题目链接: 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 0; //EOFwhile(c!='-'&&(c<'0'||c>'9')) c=getchar();sgn=(c=='-')?-1:1;ret=(c=='-')?0:(c-'0');while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');ret*=sgn;return 1;
}
struct Suffix
{int sa[maxn],rk[maxn],height[maxn];int t[maxn],t2[maxn],c[maxn],m;void init() {m=200;}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++]=0;for (i=0; i<m; i++) c[i]=0;for (i=0; i<n; i++) c[x[i]=r[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 (k=1,p=1; k<n; k*=2,m=p){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=1; i<m; i++) c[i]+=c[i-1];for (i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i];swap(x,y);p=1;x[sa[0]]=0;for (i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;}n--;}void LCP(){int i,j,k=0;for (i=1; i<=n; i++) rk[sa[i]]=i;for (i=0; i<n; i++){if (k) k--;j=sa[rk[i]-1];while (r[i+k]==r[j+k]) k++;height[rk[i]]=k;}}bool judge(int len){int l=sa[1],r=sa[1];for(int i=2;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=0,r=n,mid,ans=0;//注意ans=0,不然当n=1的时候返回的是没赋值的answhile(l<=r){int mid=l+(r-l)/2;if(judge(mid)) {ans=mid;l=mid+1;}else r=mid-1;}return ans;}
};
int main()
{//freopen("in.txt","r",stdin);//freopen("out1.txt","w",stdout);while(read(n)&&n){for(int i=0; i<n; i++) read(tmp[i]);for(int i=0; i<n-1; i++) {r[i]=tmp[i+1]-tmp[i]+90;}Suffix a;a.init();a.build();a.LCP();int ans=a.BinarySearch();if(ans<4) printf("0\n");else printf("%d\n",ans+1);}
}

13560509 neopenx 1743 Accepted 840K 407MS C++ 2761B 2014-10-24 10:20:38

转载于:https://www.cnblogs.com/neopenx/p/4047734.html

POJ 1743 (后缀数组+不重叠最长重复子串)相关推荐

  1. 后缀数组--(可重叠最长重复子串问题)

    问题描述:给定一个字符串,求最长重复子串,这两个子串可以重叠. 其实问题可以转化为height数组的最大值.至于为什么是这样,我可以这样解释: 求可重叠最长重复子串等价于求两个后缀的最长公共前缀的最大 ...

  2. #1407 : 后缀数组二·重复旋律2 (不可重叠最长重复子串问题)

    题目链接 思路 求不可重叠最长重复子串,也可以利用height[i]height[i]height[i]. 二分枚举答案KKK 当height[i]≥Kheight[i] \ge Kheight[i] ...

  3. POJ 1743 后缀数组

    题目链接:http://poj.org/problem?id=1743 题意:给定一个钢琴的音普序列[值的范围是(1~88)],现在要求找到一个子序列满足 1,长度至少为5 2,序列可以转调,即存在两 ...

  4. poj1743(后缀数组+二分--不可重叠最长重复子串)

    题目:Musical Theme #include <stdio.h> #include <string.h> #define N 1000010 int wa[N],wb[N ...

  5. 试题 算法训练 后缀数组——最长重复子串

    资源限制 时间限制:100ms 内存限制:256.0MB 问题描述 给定一个长度为n的数串,求至少出现k 次的最长重复子串的长度,这k 个子串可以重叠.保证有子串出现至少k次. 输入格式 第一行:两个 ...

  6. python求字符串中出现的第一个最长重复子串(如banana中最长重复子串为ana)

    #字符串中出现的第一个最长重复子串 class commonsubstring():def maxlen(self,s1,s2): #最长公共子串的长度for i in range(min(len(s ...

  7. 后缀数组求最长重复子串

    问题描述 给定一个字符串,求出其最长重复子串 例如:abcdabcd 最长重复子串是 abcd,最长重复子串可以重叠 例如:abcdabcda,这时最长重复子串是 abcda,中间的 a 是被重叠的. ...

  8. 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...

    最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和 文章作者:Yx.Ac   文章来源:勇幸|Thinking (http://www.ahathi ...

  9. 最长重复子串和最长不重复子串求解

    最长重复子串和最长不重复子串求解 本文内容框架: §1 最长重复子串 基本方法.KMP算法求解.后缀数组求解 §2 最长不重复子串 基本方法.动态规划.动态规划+Hash §3 小结 §1最长重复子串 ...

最新文章

  1. Java 洛谷 P1426 小鱼会有危险吗
  2. 因为世界杯!我们为你承包了整个网易~
  3. 双线性插值理论与代码实例
  4. 前端学习(3269):js中this在类中的表现
  5. Codewars-Regex Password Validation(正则检验密码格式)
  6. visio2003乱码问题
  7. 神经网络控制器设计原理,神经网络控制系统设计
  8. 备件管理系统c语言,图书管理系统的设计与开发及体育用品库存管理系统设计.doc...
  9. 立秋是中稻收割的日子
  10. 【0514 更新中】CVPR 2019 论文汇总 按方向划分
  11. Groundhog Looking Dowdy(尺取大法)
  12. IT外包:中国跃跃欲试,准备一鸣惊人——2012国际外包峰会所见所感(下)
  13. box2d的部分心得
  14. NOIP2005 篝火晚会 解题报告
  15. 判断字符长度,区分中英文(中文两个字符,英文一个字符)
  16. 使用luac加密lua文件
  17. 2020最新C#顺丰丰桥平台下单接口
  18. php表单验证_PHP表单验证:简介
  19. 小觅深度相机kalibr标定
  20. 游戏装备强化java机制,游戏装备强化类问题的数学期望

热门文章

  1. java 对象的解释过程
  2. div根据滑动页面位置显示
  3. luogu P1058 立体图
  4. c#基于socket的UDP服务器和客户端实例
  5. 对窗口过程函数WndProc()的一点理解
  6. 图像的色彩类别,灰度化,二值化
  7. c#如何将子窗体显示到父窗体的容器(panel)控件中
  8. c语言编程 完美数,用完美数的数字之美激发学生学习C语言编程的兴趣
  9. linux 多个变量,linux-BASH-使用相同“变量”的多个实例读入...
  10. mvn打包并部署本地tomcat_maven项目自动打包部署到tomcat中