POJ 1743 Musical Theme【SAM】
POJ1743 Musical Theme
要找长度\(\ge 5\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串。
题目条件中,如果对于两个串,在一个串的每个数上都加上相同的数之后可以得到另一个串,那么这个两个串可以被是相同的。
首先我们先得到差分数组,然后要求的就是差分数组中长度\(\ge 4\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串
我们需要知道的是每个等价类中终点的最左端和最右端的位置,即(\(firstpos,lastpos\)),每次新加入一个字符所得到的等价类其\(firstpos\)和\(lastpos\)必然为当前的下标,当构造完\(SAM\)之后,由于\(parent\)树的性质,\(link[u]\)所表示的等价类必然是\(u\)所表示的等价类的后缀,所以可以得到:\(lastpos[u] = max_{v\in children} lastpos[v]\)其中\(v\)是\(u\)在\(parent\)树中的儿子,而\(firstpos\)必然一直保持不变。
可以用拓扑排序然后倒序遍历来代替建\(parent\)树然后\(dfs\),拓扑排序即为按\(len\)排序,用基数排序即可
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
const int MAXN = 1e5+7;
int n,A[MAXN];
struct SAM{
int len[MAXN],link[MAXN],firstpos[MAXN],lastpos[MAXN],ch[MAXN][180],tot,last,cnt[MAXN],c[MAXN],sa[MAXN];
void init(){ link[tot = last = cnt[0] = len[0] = 0] = -1; memset(ch[0],0,sizeof(ch[0])); }
void extend(int x){
int np = ++tot, p = last; firstpos[tot] = lastpos[tot] = len[tot] = len[last] + 1;
memset(ch[tot],0,sizeof(ch[tot])); cnt[tot] = 1;
while(p!=-1 and !ch[p][x]){
ch[p][x] = np;
p = link[p];
}
if(p==-1) link[np] = 0;
else{
int q = ch[p][x];
if(len[p]+1==len[q]) link[np] = q;
else{
int clone = ++tot;
cnt[clone] = 0;
firstpos[clone] = firstpos[q];
lastpos[clone] = lastpos[q];
len[clone] = len[p] + 1;
for(int i = 0; i < 180; i++) ch[clone][i] = ch[q][i];
link[clone] = link[q];
while(p!=-1 and ch[p][x]==q){
ch[p][x] = clone;
p = link[p];
}
link[np] = link[q] = clone;
}
}
last = np;
}
int solve(){
for(int i = 0; i <= n; i++) c[i] = 0;
for(int i = 0; i <= tot; i++) c[len[i]]++;
for(int i = 1; i <= n; i++) c[i] += c[i-1];
for(int i = tot; i >= 0; i--) sa[c[len[i]]--] = i;
int ret = 0;
for(int i = tot+1; i >= 1; i--){ //这里要注意,基数排序的时候是0~tot,所以排名最后的是tot+1
int u = sa[i];
cnt[link[u]] += cnt[u];
lastpos[link[u]] = max(lastpos[link[u]],lastpos[u]);
ret = max(ret,min(len[u] + 1,lastpos[u]-firstpos[u]));
}
if(ret<5) ret = 0;
return ret;
}
}sam;
void solve(){
for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
for(int i = 1; i < n; i++) A[i] = A[i+1] - A[i] + 88;
sam.init(); for(int i = 1; i < n; i++) sam.extend(A[i]);
printf("%d\n",sam.solve());
}
int main(){
while(scanf("%d",&n)!=EOF and n) solve();
return 0;
}
POJ 1743 Musical Theme【SAM】的更多相关文章
- POJ 1743 Musical Theme 【后缀数组 最长不重叠子串】
题目冲鸭:http://poj.org/problem?id=1743 Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Su ...
- Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22499 Accepted: 7679 De ...
- poj 1743 Musical Theme【后缀自动机】
不是很神的一道题,一般. 先差分,最后答案需要+1. 一个right集的len即为该right集的最长相同后缀,考虑到不能重复,所以处理一下该right集的最大与最小的ri,最后答案ans=max(a ...
- poj 1743 Musical Theme【二分+SA】
差分,然后二分长度mid,判断是把height按照min不小于mid分组,取最大最小的sa位置看是否>=mid即可,注意差分后最后答案要+1 #include<iostream> # ...
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- poj 1743 Musical Theme(最长重复子串 后缀数组)
poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...
- Poj 1743 Musical Theme (后缀数组+二分)
题目链接: Poj 1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...
- POJ 1743 Musical Theme 后缀数组 最长重复不相交子串
Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...
- POJ 1743 Musical Theme(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1743 [题目大意] 给出一首曲子的曲谱,上面的音符用不大于88的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, ...
随机推荐
- 多媒体开发(5)&音频特征:声音可以调大一点吗?
基本上,现在常用的声音采样办法是pcm,而对于压缩音频的解码,得到的也pcm数据.这个pcm数据,只是一堆数值,有正有负,看这个值看不出什么花样. 声音采集,采的是什么呢? 采的是声音的强度变化,也是 ...
- Maven项目编译之后xml文件不存在
如题: 问题请看图,target目录是编译之后的,发现并没有对应的mapper.xml文件 原因: maven项目默认不加载此类文件 解决办法有两个: 其一是将mybatis的xml映射文件放在mav ...
- 【Flutter】容器类组件之剪裁
前言 Flutter中提供了一些剪裁函数,用于对组件进行剪裁. 剪裁Widget 作用 ClipOval 子组件为正方形时剪裁为内贴圆形,为矩形时,剪裁为内贴椭圆 ClipRRect 将子组件剪裁为圆 ...
- LeetCode226 翻转二叉树
翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 备注:这个问题是受到 Max Howell的 原问题 ...
- 【Java】变量
变量 文章目录 变量 1.变量的概念 2.变量的三要素 3.变量的使用应该注意什么? 4.变量的声明和赋值.使用的语法格式? 5.code 1.变量的概念 变量的作用:变量用来存储数据. 变量的本质: ...
- 【Oracle】Oracle 10g下载路径
ORACLE 10g下载地址 下载方法: 直接复制下面的链接,打开迅雷,自动会识别下载的内容 Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise ...
- 文件监控性能问题【BUG】
文件监控性能问题[BUG] 背景:JAVA写了一个文件夹目录监控的程序,使用的是org.apache.commons.io.monitor 包,项目稳定运行了一个月,现场反馈,文件夹数据处理越来越慢, ...
- Python机器学习笔记:奇异值分解(SVD)算法
完整代码及其数据,请移步小编的GitHub 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote 奇异值分解(Singu ...
- SDUST数据结构 - chap8 查找
选择题: 函数题: 6-1 二分查找: 裁判测试程序样例: #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 ...
- DockerFile关键字相关作用以及解释
Dockerfile 关键字 作用 备注 FROM 指定父镜像 指定dockerfile基于那个image构建 MAINTAINER 作者信息 用来标明这个dockerfile谁写的 LABEL 标签 ...