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的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, ...
随机推荐
- VMware 16.1虚拟机安装
VMware 16.1创建虚拟机 1.1首先打开我们安装好的VMware点击创建新的虚拟机 典型为自动安装,接口位默认 自定义安装更自由,可以把按需求选择 VMware16版本,只能选择Worksta ...
- js如何替换字符串中匹配到多处中某一指定节点?
抛出一个问题,如图,搜索关键字,匹配到四处,那我鼠标放在第二处,我想把它变个颜色,该怎么实现呢?回到文章的标题,js如何替换字符串中匹配到多处中某一指定节点? 字符串的替换,我们首先想到的一个属性是r ...
- MVC和MVVM的差别
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码 ...
- LeetCode542 01矩阵
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离. 两个相邻元素间的距离为 1 . 示例 1: 输入: 0 0 0 0 1 0 0 0 0 输出: 0 0 0 0 1 0 0 0 ...
- self-taught CS resouce recommendation
https://github.com/keithnull/TeachYourselfCS-CN/blob/master/TeachYourselfCS-CN.md#%E8%AE%A1%E7%AE%97 ...
- 【System】paging和swaping之间的区别是什么?
分析paging和swapping的区别,首先要了解内存管理 当虚拟内存用二级存储(物理磁盘)作为主存的扩展时,内核会尽力保持最活跃的数据在主存中.有一下两个内核例程做这件事情: 1.交换(swapp ...
- 【Linux】ABRT has detected 1 problem(s). For more info run: abrt-cli list --since 1548988705
------------------------------------------------------------------------------------------------- | ...
- 【EXPDP】导出全部表的时候,选择不导出某个表
导出的时候指定某一张表不导出的话,一般都用的是数据泵的expdp来操作 具体方法是: expdp test/test dumpfile=test.dmp directory=test_dir excl ...
- CyNix-lxd提权
0x01 信息收集 nmap -p- -T5 192.168.43.155扫描开放端口 nmap -sV -p 80,6688 -A 192.168.43.155 -oA cynix扫描指定端口 go ...
- BAPI_SALESORDER_CREATEFROMDAT2 条件 定价元素
用函数 BAPI_SALESORDER_CREATEFROMDAT2创建SO的时候,遇见个问题,就是如图: 会多出来一个类型,搞了半天,发现是一个函数里的一个参数,我没有设置: LOGIC_SWITC ...