POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串
A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of musical timing; but, this programming task is about notes and not timings.
Many composers structure their music around a repeating &qout;theme&qout;, which, being a subsequence of an entire melody, is a sequence of integers in our representation. A subsequence of a melody is a theme if it:
- is at least five notes long
- appears (potentially transposed -- see below) again somewhere else in the piece of music
- is disjoint from (i.e., non-overlapping with) at least one of its other appearance(s)
Transposed means that a constant positive or negative value is added to every note value in the theme subsequence.
Given a melody, compute the length (number of notes) of the longest theme.
One second time limit for this problem's solutions!
Input
The last test case is followed by one zero.
Output
Sample Input
30
25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
0
Sample Output
5
Hint
题解:最大不重叠相似子串。
参考代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=;
int n,s[maxn];
int rk[maxn],sa[maxn],height[maxn];
int x[maxn<<],y[maxn<<],c[maxn]; inline void get_SA(int m)
{
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=n;++i) ++c[x[i]=s[i]];
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=n;i>=;--i) sa[c[x[i]]--]=i;
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;++i) y[++num]=i;
for(int i=;i<=n;++i) if(sa[i]>k) y[++num]=sa[i]-k;
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=n;++i) ++c[x[i]];
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=n;i>=;--i) sa[c[x[y[i]]]--]=y[i],y[i]=;
swap(x,y);
x[sa[]]=;
num=;
for(int i=;i<=n;++i)
x[sa[i]]=(y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k])?num:++num;
if(num==n) break;
m=num;
}
}
inline void get_height()
{
int k=;
for(int i=;i<=n;++i) rk[sa[i]]=i;
for(int i=;i<=n;++i)
{
if(rk[i]==) continue;
if(k) --k;
int j=sa[rk[i]-];
while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k]) ++k;
height[rk[i]]=k;
}
}
bool check(int k)
{
int mx=-INF,mi=INF;
for(int i=;i<=n;++i)
{
if(height[i]>=k)
{
mx=max(mx,max(sa[i],sa[i-]));
mi=min(mi,min(sa[i],sa[i-]));
if(mx-mi>k) return true;
}
else mx=-INF,mi=INF;
}
return false;
} int main()
{
while(scanf("%d",&n) && n)
{
int pre,now; n--;
scanf("%d",&pre);
for(int i=;i<=n;++i) scanf("%d",&now),s[i]=now-pre+,pre=now;
get_SA();
get_height(); int l=,r=n>>;
while(l+<r)
{
int mid=l+r>>;
if(check(mid)) l=mid;
else r=mid;
}
int ans;
if(check(r)) ans=r;
else ans=l;
printf("%d\n",ans>=? ans+:);
} return ;
}
后缀自动机
/********* 后缀自动机做法 ***********/
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 1000000000
#define mod 1000000007
#define pa pair<int,int>
#define ll long long
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,a[];
struct sam{
int last,cnt,ans;
int l[],r[],mx[],fa[],a[][];
int q[],v[];
void init()
{
memset(l,,sizeof(l));
memset(r,,sizeof(r));
memset(v,,sizeof(v));
memset(mx,,sizeof(mx));
memset(fa,,sizeof(fa));
memset(a,,sizeof(a));
last=cnt=;ans=;
}
void extend(int c)
{
int p=last,np=last=++cnt;mx[np]=mx[p]+;
l[np]=r[np]=mx[np];
while(!a[p][c]&&p)a[p][c]=np,p=fa[p];
if(!p)fa[np]=;
else
{
int q=a[p][c];
if(mx[p]+==mx[q]) fa[np]=q;
else
{
int nq=++cnt;mx[nq]=mx[p]+;
memcpy(a[nq],a[q],sizeof(a[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
while(a[p][c]==q) a[p][c]=nq,p=fa[p];
}
}
}
void solve()
{
for(int i=;i<=cnt;i++) v[mx[i]]++;
for(int i=;i<=n;i++) v[i]+=v[i-];
for(int i=cnt;i;i--) q[v[mx[i]]--]=i;
for(int i=cnt;i;i--)
{
int p=q[i];
l[fa[p]]=min(l[fa[p]],l[p]);
r[fa[p]]=max(r[fa[p]],r[p]);
}
for(int i=;i<=cnt;i++)
ans=max(ans,min(mx[i],r[i]-l[i]));
if(ans<)puts("");
else printf("%d\n",ans+);
}
} sam;
int main()
{
while(scanf("%d",&n))
{
if(n==)break;
for(int i=;i<=n;i++) a[i]=read();n--;
for(int i=;i<=n;i++) a[i]=a[i+]-a[i]+;
sam.init();
for(int i=;i<=n;i++)
sam.extend(a[i]);
sam.solve();
}
return ;
}
POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串的更多相关文章
- POJ1743 Musical Theme(二分+后缀数组)
题目大概是给n个数组成的串,求是否有多个“相似”且不重叠的子串的长度大于等于5,两个子串相似当且仅当长度相等且每一位的数字差都相等. 这题是传说中楼教主男人八题之一,虽然已经是用后缀数组解决不可重叠最 ...
- poj 1743 后缀数组 求最长不重叠重复子串
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. “主题”是整个音符序列的一个子串,它需要满足如下条件:1 ...
- Musical Theme - poj 1743(求最大不重叠重复子串)
题目大意: * 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题. * “主题”是整个音符序列的一个子串,它需要满 ...
- POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串
题目链接:https://vjudge.net/problem/POJ-1743 Musical Theme Time Limit: 1000MS Memory Limit: 30000K Tot ...
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...
- 【整理】如何选取后缀数组&&后缀自动机
后缀家族已知成员 后缀树 后缀数组 后缀自动机 后缀仙人掌 后缀预言 后缀Splay ? 后缀树是后缀数 ...
- loj6173 Samjia和矩阵(后缀数组/后缀自动机)
题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...
- 利用后缀数组(suffix array)求最长公共子串(longest common substring)
摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其 ...
- poj 3693 后缀数组 重复次数最多的连续重复子串
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8669 Acc ...
- 笔试算法题(40):后缀数组 & 后缀树(Suffix Array & Suffix Tree)
议题:后缀数组(Suffix Array) 分析: 后缀树和后缀数组都是处理字符串的有效工具,前者较为常见,但后者更容易编程实现,空间耗用更少:后缀数组可用于解决最长公共子串问题,多模式匹配问题,最长 ...
随机推荐
- 【Swift】UNNotificationServiceExtension
一.简介 An object that modifies the content of a remote notification before it's delivered to the user. ...
- 201871010114-李岩松《面向对象程序设计(java)》第十二周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- jsp+servlet分页查询
分页查询 减少服务器内存开销 提高用户体验 效果图 思绪图 分页显示Bean文件代码 package cn.ytmj.findlist.domain; import java.util.List; / ...
- windows系统cmd命令行窗口查看端口占用情况
# 查看所有在用端口 netstat -ano # 查看指定端口 netstat -ano | findstr 8899 # 结束该进程:taskkill /f /t /im javaw.exe:或者 ...
- PHP 面试官问:你说说Redis的几个过期策略?
在使用redis时,一般会设置一个过期时间,当然也有不设置过期时间的,也就是永久不过期.当设置了过期时间,redis是如何判断是否过期,以及根据什么策略来进行删除的. 设置过期时间 expire ke ...
- 我的第一个 60 k+ Star Java开源项目
JavaGuide([Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识):https://github.com/Snailclimb/JavaGuide. 人生总有各种各样的 ...
- pat 1149 Dangerous Goods Packaging(25 分)
1149 Dangerous Goods Packaging(25 分) When shipping goods with containers, we have to be careful not ...
- Java的String类详解
Java的String类 String类是除了Java的基本类型之外用的最多的类, 甚至用的比基本类型还多. 同样jdk中对Java类也有很多的优化 类的定义 public final class S ...
- cn_windows虚拟机配置
1.打开“VMware”,点击“主页”,点“创建新的虚拟机”: 2.会弹出一个“新建虚拟机向导”,类型选择“典型”,点击“下一步”: 3.选择“稍后安装操作系统”,点击“下一步”: 4.选择“Micr ...
- RHEL7.2 SSH无密码登录非root用户
1 修改三台虚拟机的/ect/hosts文件 [hadoop@hadoop01 ~]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain ...