Musical Theme

题意

给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件:

  1. 长度大于5
  2. 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x)

思路

我们处理一下这个所谓的“变调”:令\(a[i]=a[i+1]-a[i]\),这样就转化成了找最长的出现至少两次的不重叠子串。(这时长度变为n-1)

两种做法:1.二分+ hash 2. 二分+后缀数组

使用hash的时候,对于当前二分的长度x。

我们从x开始遍历到n,如果[i-x+1,i]的hash值已经出现在i-x之前过,当前长度就可以,因为这个hash值是unsigned long long 范围,我们要使用map来判断,然后就会发现超时。

百度时候发现,题解的map是自己写的。

struct hashmap
{
int head[Hash],next[N],sz,f[N];
/*
使用邻接表把%Hash相同的数字串起来
state[i]放的是具体的值
f[i]放的是值的下标
sz是存的数字的数量
*/
ull state[N];
void init()
{
sz=0;
memset(head,-1,sizeof(head));
}
int add(ull val,int id)
{
int now=val%Hash;
for(int i=head[now]; i!=-1; i=next[i])
{
if(val==state[i])//val已经出现过,返回第一次出现的下标
return f[i];
}
/*val没有出现,加入到hashmap中*/
state[sz]=val;
f[sz]=id;
next[sz]=head[now];
head[now]=sz++;
return f[sz-1];
}
} mp;

使用后缀数组。

引自[后缀数组——处理字符串的有力工具]----罗穗骞

先二分答案,把题目变成判定性问题:判断是否存在两个长度为k的子串是相同的,且不重叠。解决这个问题的关键还是利用height数组。把排序后的后缀分成若干组,其中每组的后缀之间的height值都不小于k。例如,字符串为“aabaaaab”,当k=2时,后缀分成了4组,如图所示。

容易看出,有希望成为最长公共前缀不小于k的两个后缀一定在同一组。然后对于每组后缀,只须判断每个后缀的sa值的最大值和最小值之差是否不小于k。如果有一组满足,则说明存在,否则不存在。整个做法的时间复杂度为O(nlogn)。本文中利用height值对后缀进行分组的方法很常用,请读者认真体会

后缀数组代码

// #include <bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f; int cnt[N],oldrk[N],rk[N],sa[N],pos[N],ht[N];
int n,m;
int arr[N]; bool cmp(int x,int y,int k)
{
return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];
}
void getsa()
{
memset(cnt,0,sizeof(cnt));
m=200;
for(int i=1; i<=n; i++)
++cnt[rk[i]=arr[i]];
for(int i=1; i<=m; i++)
cnt[i]+=cnt[i-1];
for(int i=n; i; i--)
sa[cnt[rk[i]]--]=i;
for(int k=1; k<=n; k<<=1)
{
int num=0;
for(int i=n-k+1; i<=n; i++)
pos[++num]=i;
for(int i=1; i<=n; i++)
{
if(sa[i]>k)
pos[++num]=sa[i]-k;
}
memset(cnt,0,sizeof(cnt));
for(int i=1; i<=n; i++)
++cnt[rk[i]];
for(int i=1; i<=m; i++)
cnt[i]+=cnt[i-1];
for(int i=n; i; i--)
sa[cnt[rk[pos[i]]]--]=pos[i];
num=0;
memcpy(oldrk,rk,sizeof(rk));
for(int i=1; i<=n; i++)
rk[sa[i]]=cmp(sa[i],sa[i-1],k)?num:++num;
if(m==n)
break;
m=num;
}
for(int i=1; i<=n; i++)
rk[sa[i]]=i;
int k=0;
for(int i=1; i<=n; i++)
{
if(k)
--k;
while(arr[i+k]==arr[sa[rk[i]-1]+k])
++k;
ht[rk[i]]=k;
}
}
int judge(int x)
{
int minn=sa[1],maxn=sa[1];
for(int i=2; i<=n; i++)//精辟
{
if(ht[i]>=x)
{
maxn=max(maxn,sa[i]);
minn=min(minn,sa[i]);
}
else
{
minn=sa[i];
maxn=sa[i];
}
if(maxn-minn>x)
return 1;
}
return 0;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=1; i<=n; i++)
scanf("%d",&arr[i]);
for(int i=1; i<n; i++)
arr[i]=arr[i+1]-arr[i]+100;
n--;
getsa();
int l=4,r=n/2,ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(judge(mid))
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
if(!ans)
printf("0\n");
else
printf("%d\n",ans+1);
}
return 0;
}

hash代码

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<map>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e4 + 10;
const int mod = 1610612741;
const int inf = 0x3f3f3f3f;
const int Hash=10007; ull hash1[N],bin[N];
int n,arr[N],brr[N];
ull get(int l,int r)
{
return hash1[r]-hash1[l-1]*bin[r-l+1];
}
struct hashmap
{
int head[Hash],next[N],sz,f[N];
ull state[N];
void init()
{
sz=0;
memset(head,-1,sizeof(head));
}
int add(ull val,int id)
{
int now=val%Hash;
for(int i=head[now]; i!=-1; i=next[i])
{
if(val==state[i])
return f[i];
}
state[sz]=val;
f[sz]=id;
next[sz]=head[now];
head[now]=sz++;
return f[sz-1];
}
} mp;
int judge(int x)
{
mp.init();
for(int i=x; i<n; i++)
{
if(mp.add(get(i-x+1,i),i)<i-x)
return 1;
}
return 0; }
int main()
{
bin[0]=1;
for(int i=1; i<=20000; i++)
bin[i]=bin[i-1]*137;
while(~scanf("%d",&n)&&n)
{
for(int i=1; i<=n; i++)
scanf("%d",&arr[i]);
for(int i=1;i<n;i++)
{
arr[i]=arr[i+1]-arr[i];
hash1[i]=hash1[i-1]*137+arr[i];
}
int l=4,r=n/2-1,ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(judge(mid))
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
if(!ans)
printf("0\n");
else
printf("%d\n",ans+1);
}
return 0;
}

[poj 1743] Musical Theme 后缀数组 or hash的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. POJ.1743.Musical Theme(后缀数组 倍增 二分 / 后缀自动机)

    题目链接 \(Description\) 给定一段数字序列(Ai∈[1,88]),求最长的两个子序列满足: 1.长度至少为5 2.一个子序列可以通过全部加或减同一个数来变成另一个子序列 3.两个子序列 ...

  8. POJ 1743 Musical Theme 后缀数组 不可重叠最长反复子串

    二分长度k 长度大于等于k的分成一组 每组sa最大的和最小的距离大于k 说明可行 #include <cstdio> #include <cstring> #include & ...

  9. poj 1743 Musical Theme 后缀自动机/后缀数组/后缀树

    题目大意 直接用了hzwer的题意 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题."主题&qu ...

随机推荐

  1. C - Mind Control CodeForces - 1291C

    菜到家了,题意都读不懂. 题目大意: 总共有n个人和n个数字 n个人拍成一队,n个数字也是有顺序的 你排在第m个位置 按照顺序的每个人可以拿走这个序列中的第一个数字或者最后一个数字 你可以在所有人操作 ...

  2. windows搭建Selenium

    安装 pip install -U selenium 安装浏览器驱动 用不同的浏览器需要安装不同的驱动,驱动放置的路径添加到path中. Firefox geodriver Chrome 下载驱动Ch ...

  3. SpringBoot集成Shiro实现权限控制

    Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...

  4. 简单了解下CAP定理与BASE定理

    分布式环境下的各种问题 通信异常 网络不可用风险高,消息丢失.消息延迟非常普遍 网络分区(脑裂)   网络发生异常情况,延迟增加,导致所有组成分布式系统的节点中,只有部分节点之间能够正常通信,而另一些 ...

  5. 【转】动态规划之最长公共子序列(LCS)

    [原文链接]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套 ...

  6. Spring5:Java Config

    @Configuration @Bean @ComponentScan @ImportResource 使用Java的方式配置spring,完全不使用spring配置文件,交给java来做! 两个注解 ...

  7. MySQL笔记总结-TCL语言

    TCL语言 事务 一.含义 事务控制语言 Transaction Control Language 事务:一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行 二.特点(ACID ...

  8. ACNet: 特别的想法,腾讯提出结合注意力卷积的二叉神经树进行细粒度分类 | CVPR 2020

    论文提出了结合注意力卷积的二叉神经树进行弱监督的细粒度分类,在树结构的边上结合了注意力卷积操作,在每个节点使用路由函数来定义从根节点到叶子节点的计算路径,结合所有叶子节点的预测值进行最终的预测,论文的 ...

  9. Solr搜索结果高级设置

    一.选择响应格式 XML是Solr的默认响应格式.从Solr的角度看,什么样的响应格式并不重要.Solr可以返回XML.JSON.Ruby.Python.PHP.二进制Java等,甚至是自定义格式.使 ...

  10. 关于ubuntu安装vmware报错问题解决

    命令行中报错 首先报错内容为:(vmware-installer.py:3847): Gtk-WARNING **: 无法在模块路径中找到主题引擎:“murrine”, 以上的内容: sudo apt ...