poj 1743 后缀数组 求最长不重叠重复子串
题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。
“主题”是整个音符序列的一个子串,它需要满足如下条件:
1.长度至少为5个音符
2.在乐曲中重复出现(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值。)
3.重复出现的同一主题不能有公共部分。
链接:点我
先转化成相邻两项的差值,然后就是找不可重叠重复子串。
做法就是二分答案LEN
然后根据height值进行分组
第一道后缀数组题,测了一下模板
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=0x3f3f3f3f;
const double eps=1e-;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
int n,m,tt;
/*
*suffix array
*倍增算法 O(n*logn)
*待排序数组长度为n,放在0~n-1中,在最后面补一个0
*da(str ,n+1,sa,rank,height, , );//注意是n+1;
*例如:
*n = 8;
*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
*
*/
const int MAXN=; char str[MAXN];
int r[MAXN];
int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];//求SA数组需要的中间变量,不需要赋值
//待排序的字符串放在s数组中,从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0,r[n-1]=0
//函数结束以后结果放在sa数组中
bool cmp(int *r,int a,int b,int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
//第一轮基数排序,如果s的最大值很大,可改为快速排序
for(i = ;i < m;i++)c[i] = ;
for(i = ;i < n;i++)c[x[i] = str[i]]++;
for(i = ;i < m;i++)c[i] += c[i-];
for(i = n-;i >= ;i--)sa[--c[x[i]]] = i;
for(j = ;j <= n; j <<= )
{
p = ;
//直接利用sa数组排序第二关键字
for(i = n-j; i < n; i++)y[p++] = i;//后面的j个数第二关键字为空的最小
for(i = ; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;
//这样数组y保存的就是按照第二关键字排序的结果
//基数排序第一关键字
for(i = ; i < m; i++)c[i] = ;
for(i = ; i < n; i++)c[x[y[i]]]++;
for(i = ; i < m;i++)c[i] += c[i-];
for(i = n-; i >= ;i--)sa[--c[x[y[i]]]] = y[i];
//根据sa和x数组计算新的x数组
swap(x,y);
p = ; x[sa[]] = ;
for(i = ;i < n;i++)
x[sa[i]] = cmp(y,sa[i-],sa[i],j)?p-:p++;
if(p >= n)break;
m = p;//下次基数排序的最大值
}
int k = ;
n--;
for(i = ;i <= n;i++)rank[sa[i]] = i;
for(i = ;i < n;i++)
{
if(k)k--;
j = sa[rank[i]-];
while(str[i+k] == str[j+k])k++;
height[rank[i]] = k;
}
}
int rank[MAXN],height[MAXN];
int s[MAXN];
bool check(int n,int k)
{
int Max=sa[],Min=sa[];
for(int i=;i<=n;i++)
{
if(height[i]<k)Max=Min=sa[i];
else
{
if(sa[i]<Min)Min=sa[i];
if(sa[i]>Max)Max=sa[i];
if(Max-Min>k)return true;
}
}
return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d",&n)== && n)
{
for(int i=;i<n;i++)scanf("%d",&s[i]);
for(int i=n-;i>;i--)s[i]=s[i]-s[i-]+;
n--;//减少一个长度
for(int i=;i<n;i++)s[i]=s[i+];
s[n]=;
da(s,sa,rank,height,n,);
int ans=-;
int l=,r=n/;
while(l<=r)
{
int mid=(l+r)/;
if(check(n,mid))
{
ans=mid;
l=mid+;
}
else r=mid-;
}
if(ans<)printf("0\n");
else printf("%d\n",ans+);
}
return ;
}
poj 1743 后缀数组 求最长不重叠重复子串的更多相关文章
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)
永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)
题目链接:http://poj.org/problem?id=1743 题目理解起来比较有困难,其实就是求最长有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1 ...
- Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22499 Accepted: 7679 De ...
- poj 1743 后缀数组 最长不重叠子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 30941 Accepted: 10336 D ...
- [八分之一的男人]POJ - 1743 后缀数组 height分组 带详解
题意:求最长不可重叠的相同差值子串的长度 这道题算是拖了好几个月,现在花了点时间应该搞懂了不少,尝试分析一下 我们首先来解决一个退化的版本,求最长不可重叠的相同子串(差值为0) 比如\(aabaaba ...
- POJ 1743 (后缀数组+不重叠最长重复子串)
题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律 ...
- POJ 1743 后缀数组
题目链接:http://poj.org/problem?id=1743 题意:给定一个钢琴的音普序列[值的范围是(1~88)],现在要求找到一个子序列满足 1,长度至少为5 2,序列可以转调,即存在两 ...
- poj2774 Long Long Message 后缀数组求最长公共子串
题目链接:http://poj.org/problem?id=2774 这是一道很好的后缀数组的入门题目 题意:给你两个字符串,然后求这两个的字符串的最长连续的公共子串 一般用后缀数组解决的两个字符串 ...
随机推荐
- Coursera在线学习---第四节.过拟合问题
一.解决过拟合问题方法 1)减少特征数量 --人为筛选 --靠模型筛选 2)正则化(Regularization) 原理:可以降低参数Θ的数量级,使一些Θ值变得非常之小.这样的目的既能保证足够的特征变 ...
- Android 开发笔记(一) 按钮事件调用Activity
UI创建按钮及事件 Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);mEmailSignInB ...
- python 之ConfigParser模块学习
1.1 读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该secti ...
- windows 10添加定时任务
1.在搜索栏搜索‘任务计划’ 2.选择任务计划程序,打开 3.创建基本任务 4.输入任务名称 5.选择任务触发周期 6.选择任务触发的具体时间点 7.选择任务需要做的事 8.选择启动程序后,选择具体的 ...
- 7.Python3标准库--文件系统
''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...
- 用OpenSSL命令行生成证书文件
用OpenSSL命令行生成证书文件 1.首先要生成服务器端的私钥(key文件): openssl genrsa -des3 -out server.key 1024 运行时会提示输入密码,此密码用于加 ...
- Codeforces Round #423 Div. 2 C-String Reconstruction(思维)
题目大意:告诉你n个字符串以及这些字符串在字符串s中出现的位置(x1,x2.....xn),要求在满足上述条件的情况下,求出字典序最小的字符串s. 解题思路:主要问题是,如果直接模拟是会超时的,比如v ...
- 观察者模式和java委托
观察者模式与java委托 所谓观察者模式,指的某个状态信息的改变,会影响其他一系列的操作,这时就可以将这些操作抽象化,同时创建一个类统一的管理和执行这些操作.把这些抽象出来的操作称为观察者类,而管理这 ...
- ISSCC 2017论文导读 Session 14 Deep Learning Processors,DNPU: An 8.1TOPS/W Reconfigurable CNN-RNN
转载请注明,本文出自Bin的专栏http://blog.csdn.net/xbinworld,谢谢! DNPU: An 8.1TOPS/W Reconfigurable CNN-RNN Process ...
- 使用jdk自带的工具native2ascii 转换Unicode字符和汉字
1.控制台转换 1.1 将汉字转为Unicode: C:\Program Files\Java\jdk1.5.0_04\bin>native2ascii 测试 \u6d4b\u8bd5 1.2 ...