题目链接:https://cn.vjudge.net/contest/283743#problem/C

题目大意:给你n个数组,然后问你是否有多个“相似”且不重叠的子串的长度大于等于5(两个子串相似当且仅当长度相等且每一位的数字差都相等)。

具体思路:对于相似,我们直接对于当前的输入的和他的上一位相减就可以了,这样差就表示出来了,然后就开始判断时候有相同的子串并且不重叠并且长度>=5就可以了。判断的时候,首先分组,分组的标准是这个组里面的height是不是大于等k,对于每一个组,找出最大的sa差值,然后就判断差值和5的关系就可以了。对于具体的原因,height[i]数组指的是排序之后,排名为i和i-1的最长公共前缀,然后再分组的时候,如果height数组>=k的时候,就直接判断这两个字符串的开头位置就可以了,这个可以通过sa数组实现。

AC代码:

 #include<iostream>
#include<stack>
#include<cstring>
#include<iomanip>
#include<stdio.h>
#include<algorithm>
#include<cmath>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 5e5+;
int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn];
int Rank[maxn];
int ch[maxn];
int sto[maxn];
ll n;
//sa[i]代表第i小的后缀位置,Rank[i]代表第i位置的后缀,排名第几小
// height[i]代表排名第i个字符串和第i-1个字符串的相同前缀有多少个
void cal()
{
for(int i = ; i < ; i++)
cntA[i] = ;
// cout<<1<<endl;
// cout<<n<<endl;
for(int i = ; i <= n; i++){
//cout<<ch[i-1]<<endl;
cntA[ch[i-]]++;
}
// cout<<1<<endl;
for(int i = ; i < ; i++)
cntA[i] += cntA[i-];
for(int i = n; i; i--)
sa[cntA[ch[i-]]--] = i;
Rank[sa[]] = ;
for(int i = ; i <= n; i++)
{
Rank[sa[i]] = Rank[sa[i-]];
if(ch[sa[i]-] != ch[sa[i-]-])
Rank[sa[i]]++;
}
for(int l = ; Rank[sa[n]] < n; l <<= )
{
memset(cntA, , sizeof(cntA));
memset(cntB, , sizeof(cntB));
for(int i = ; i <= n; i++)
{
cntA[A[i] = Rank[i]]++;
cntB[B[i] = (i+l <= n)?Rank[i+l]:]++;
}
for(int i = ; i <= n; i++)
cntB[i] += cntB[i-];
for(int i = n; i; i--)
tsa[cntB[B[i]]--] = i;
for(int i = ; i <= n; i++)
cntA[i] += cntA[i-];
for(int i = n; i; i--)
sa[cntA[A[tsa[i]]]--] = tsa[i];
Rank[sa[]]=;
for(int i = ; i <= n; i++)
{
Rank[sa[i]] = Rank[sa[i-]];
if(A[sa[i]] != A[sa[i-]] || B[sa[i]] != B[sa[i-]])
Rank[sa[i]]++;
}
}
for(int i = , j = ; i <= n; i++)
{
if(j)
j--;
while(ch[i+j-] == ch[sa[Rank[i]-] + j - ])
j++;
height[Rank[i]] = j;
}
}
bool judge(int t)
{
int mx=-inf,mm=inf;
for(int i=; i<=n; i++)
{
if(height[i]>=t)
{
mm=min(mm,min(sa[i],sa[i-]));
mx=max(mx,max(sa[i],sa[i-]));
if(mx-mm>t)
return true;
}
else
{
mm=inf;
mx=-inf;
}
}
return false;
}
int main()
{
// int n;
while(scanf("%d",&n)&&n)
{
for(int i=; i<n; i++)
{
scanf("%d",&sto[i]);
}
for(int i=; i<n; i++)
{
ch[i]=sto[i+]-sto[i]+;
}
n--;
cal();
int ans=-;
int l=,r=1e8;
while(l<=r)
{
int mid=(l+r)>>;
// cout<<l<<" "<<r<<endl;
if(judge(mid))
{
ans=mid;
l=mid+;
// cout<<ans<<endl;
}
else
{
r=mid-;
}
}
if(ans>=)
printf("%d\n",ans+);
else
{
printf("0\n");
}
}
return ;
}

C - Musical Theme (后缀数组)的更多相关文章

  1. POJ1743 Musical Theme [后缀数组]

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

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

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

  3. POJ1743 Musical Theme [后缀数组+分组/并查集]

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

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

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

  5. POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串

    题目链接:https://vjudge.net/problem/POJ-1743 Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Tot ...

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

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

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

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

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

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

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

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

  10. [Poj1743] [后缀数组论文例题] Musical Theme [后缀数组不可重叠最长重复子串]

    利用后缀数组,先对读入整数处理str[i]=str[i+1]-str[i]+90这样可以避免负数,计算Height数组,二分答案,如果某处H<lim则将H数组分开,最终分成若干块,判断每块中是否 ...

随机推荐

  1. UOJ #76 【UR #6】懒癌

    确实是一道很不错的题啊. 题目链接 题意 感觉也没什么特别简洁的版本,大家直接看题面吧. 题解 我第一次看到这个类似问题的背景是疯狗,因此下面的题解不自觉的代入了...大家明白意思就好. 我们考虑对于 ...

  2. Markdown 文件转化为work文档

    1. 电脑安装pandoc 链接:https://pan.baidu.com/s/12H5wLO0JWph5TjrbeJI6mg 密码:ssgs 下载安装包解压即可用.记得配置系统环境变量 2.命令行 ...

  3. .net event 使用 Action

    Action<string> methodCall = (x) => { x += "haha"; MessageBox.Show(x); }; public e ...

  4. 自学Linux Shell8.1-linux文件系统概述及操作

    点击返回 自学Linux命令行与Shell脚本之路 8.1-linux文件系统概述及操作 1. linux支持的文件系统 Windows常用的分区格式有三种,分别是FAT16.FAT32.NTFS格式 ...

  5. if语句实例

    if 单分支#!/bin/bashRATE=`df -hT | grep "/boot" | awk '{print $6}' | cut -d "%" -f1 ...

  6. Java8的Stream流(一) --- 基础用法

    Java8中的Stream Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象. Stream的特性及优点: 无存储. Stream不是一种数据 ...

  7. 在Android中通过Intent使用Bundle传递对象

    IntentBundle传递对象SerializableParcelable Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法.被传递的对象 ...

  8. Ubuntu安装Atom编辑器

    安装方法 执行以下命令 sudo add-apt-repository ppa:webupd8team/atom sudo apt-get update udo apt-get install ato ...

  9. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  10. C# winform C/S WebBrowser qq第三方授权登录

    qq的授权登录,跟微信相似,不同的地方是: 1 申请appid与appkey的时候,注意填写回调地址. 2 这里可以在WebBrowser的是Navigated事件中直接得到Access Token, ...