洛谷P2743传送门

题目大意:给你一个序列,求其中最长的一对相似等长子串

一对合法的相似子串被定义为:

1.任意一个子串长度都大于等于5

2.不能有重叠部分

3.其中一个子串可以在全部+/-某个值后和另一个串完全相同

还是老套路了,其实只要求出每一项和前一项的差值序列,这样第三个问题可以被转化为求最长不重叠的相同子串,最后把答案+1就行了

这道题竟然还是LTC大佬的男人八题!正解是后缀数组+二分,但据说可以n^2骗分过

思路是先求出height数组,对于排序后的字符串集合有一个神奇的性质,如果有某连续的几个字符串height>=x,那么这几个字符串的公共前缀长度>=x,可以用Trie树的思想很容易地证明

那现在就要解决第二个问题,不能有重叠部分

直接求解不容易,所以我们二分答案去做,每次二分出一个答案x,然后去height数组里找,把连续的几个height>=x字符串想象成一块,那么如果这个块合法,这一块内一定存在两个字符串的sa[i]-sa[j]>=x,也就是在这一块内找出sa[i]的最大最小值就行啦

复杂度O(nlogn)

傻了吧唧的把后缀数组敲错了,调了半个小时

 #include <cstdio>
#include <cstring>
#include <algorithm>
#define N 20010
#define inf 0x3f3f3f3f
#define maxn 100
using namespace std; int n,len;
int a[N],b[N],tr[N],rk[N],sa[N],hs[N],h[N];
int gint()
{
int rett=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){rett=(rett<<)+(rett<<)+c-'';c=getchar();}
return rett*fh;
}
void clr()
{
memset(a,,sizeof(a));memset(tr,,sizeof(tr));
memset(b,,sizeof(b));memset(rk,,sizeof(rk));
memset(h,,sizeof(h));memset(sa,,sizeof(sa));
memset(hs,,sizeof(hs));
}
bool check(int k,int x,int y){
if(x+k>len||y+k>len) return ;
else return (rk[x]==rk[y]&&rk[x+k]==rk[y+k])?:;
}
void get_sa()
{
int cnt=,i=;
for(i=;i<=n;i++) hs[b[i]]++;
for(i=;i<=*maxn;i++) if(hs[i]) tr[i]=++cnt;
for(i=;i<=*maxn;i++) hs[i]+=hs[i-];
for(i=;i<=n;i++) rk[i]=tr[b[i]],sa[hs[b[i]]--]=i;
for(int k=;cnt<len;k<<=)
{
for(i=;i<=cnt;i++) hs[i]=;
for(i=;i<=len;i++) hs[rk[i]]++;
for(i=;i<=cnt;i++) hs[i]+=hs[i-];
for(i=len;i>=;i--) if(sa[i]>k) tr[sa[i]-k]=hs[rk[sa[i]-k]]--;
for(i=;i<=k;i++) tr[len-i+]=hs[rk[len-i+]]--;
for(i=;i<=len;i++) sa[tr[i]]=i;
for(i=,cnt=;i<=len;i++) tr[sa[i]]=check(k,sa[i],sa[i-])?cnt:++cnt;
for(i=;i<=len;i++) rk[i]=tr[i];
}
}
void get_height()
{
for(int i=;i<=len;i++){
if(rk[i]==) continue;
for(int j=max(,h[rk[i-]]-);j;j++)
if(b[i+j-]==b[sa[rk[i]-]+j-]) h[rk[i]]=j;
else break;
}
}
bool check(int ans)
{
int i=,j=;
for(i=;i<=len;)
{
if(h[i]<ans) {i++;continue;}
int mi=sa[i-],ma=sa[i-];
for(;h[i]>=ans&&i<=len;i++)
{
mi=min(mi,sa[i]);
ma=max(ma,sa[i]);
if(ma-mi>ans) return ;
}
}return ;
} int main()
{
while(scanf("%d",&n)&&n!=)
{
len=n;
clr();
for(int i=;i<=n;i++)
a[i]=gint(),b[i]=a[i]-a[i-]+maxn;
get_sa();
get_height();
int l=,r=n,ans=;
while(l<=r){
int mid=(l+r)>>;
if(check(mid)) ans=mid,l=mid+;
else r=mid-;
}
if(ans<) printf("0\n");
else printf("%d\n",ans+);
}
return ;
}

POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)的更多相关文章

  1. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  2. Poj 1743 Musical Theme (后缀数组+二分)

    题目链接: Poj  1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...

  3. POJ1743 Musical Theme(后缀数组 二分)

    Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 33462   Accepted: 11124 Description A m ...

  4. POJ 1743 Musical Theme ——后缀数组

    [题目分析] 其实找最长的不重叠字串是很容易的,后缀数组+二分可以在nlogn的时间内解决. 但是转调是个棘手的事情. 其实只需要o(* ̄▽ ̄*)ブ差分就可以了. 背板题. [代码] #include ...

  5. POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

    Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...

  6. poj 1743 Musical Theme (后缀数组+二分法)

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16162   Accepted: 5577 De ...

  7. [poj 1743] Musical Theme 后缀数组 or hash

    Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...

  8. POJ 1743 Musical Theme ( 后缀数组 && 最长不重叠相似子串 )

    题意 : 给 n 个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等. 分析 :  根据题目对于 “ 相似 ” 串的定义,我们可以将原 ...

  9. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

随机推荐

  1. MAVEN 构建包的引用

    1.什么叫构建包的引用? 当你存在两个maven项目分别是项目A,项目B时,且项目B要引用项目A的方法,那么你就用把项目A打成*.jar架包,放到本地的Maven仓库提供给项目B去引用. A.用命令到 ...

  2. 深入了解Python--元组

    1. 对原元组进行插入 2. 元组的嵌套使用 3. for循环使用嵌套元组实例 4. 命名元组避免对分片混淆

  3. 【Educational Codeforces Round 48 (Rated for Div. 2) D】Vasya And The Matrix

    [链接] 我是链接,点我呀:) [题意] 告诉你每一行.每一列的异或和. 让你求出一个符合要求的原矩阵. [题解] 显然应该有 a1^a2^....^an = b1^b2^....^bn 也即两边同时 ...

  4. ZOJ 3888 Twelves Monkeys

    Twelves Monkeys Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Origina ...

  5. NHibernate之旅(18):初探代码生成工具使用

    本节内容 引入 代码生成工具 结语 引入 我们花了大量的篇幅介绍了相关NHibernate的知识.一直都是带着大家手动编写代码,首先创建数据库架构.然后编写持久化类和映射文件,最后编写数据操作方法.測 ...

  6. 编程算法 - 求1+2+...+n(模板类) 代码(C++)

    求1+2+...+n(模板类) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 求1+2+...+n, 要求不能使用乘除法\for\whil ...

  7. 树莓派与window 10组成的物联网核心:让人失望

    去年春天,微软公布了自己的window系统与物联网系统的方案,该方案使用树莓派和window 10组成物联网的核心.树莓派是一个与window全然不同的执行在ARM构架下的系统. 是的,也许微软决心离 ...

  8. node-webkit 屏幕截图功能

    做 IM 屏幕截图是少不了的,之前 windows 版本是调用的 qq 输入法的截图功能,这个版本又再次尝试自己实现发现是可以的,getusermedia 的权限很高,代码如下 <!DOCTYP ...

  9. Codeforces Round #260 (Div. 1) 455 A. Boredom (DP)

    题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory l ...

  10. 0x27 A*

    终于完全了解A*到底是什么玩意儿了 对于当前的决策,选取当前花费+预估花费最小来拓展. 因为假如预估出现失误,那么很可能就会延伸到一个错误的决策点,而这个决策点偏偏就是ed,而由于预估失误,其他点的当 ...