POJ 3693 (后缀数组) Maximum repetition substring
找重复次数最多的字串,如果有多解,要求字典序最小。
我也是跟着罗穗骞菊苣的论文才刷这道题的。
首先还是枚举一个循环节的长度L,如果它出现两次的话,一定会包含s[0], s[L], s[2L]这些相邻两个之间。
然后枚举相邻的两个,尽可能的向前和向后延伸,假设延伸长度为k,则重复次数为k / L + 1
向后延伸很自然的就是求一次LCP,这个用RMQ预处理一下就可以O(1)查询。
向前延伸就是考虑到,我们枚举的s[i*L]和s[(i+1)*L]并不一定是字串的开头,所以向前移动i - (k % i)个位置。
为什么向前移动这么多,就是因为这样的话,LCP的长度就正好是i的整数倍了。
所以向前移动以后,再求一次LCP,看看能否够i - (k % i)这么多,够的话这个串的重复次数再加1.
至于要字典序最小,就得用height数组天生自带字典序。把所有重复次数最多的长度记录下来,然后按字典序枚举,只要找到一组就输出。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
char s[maxn];
int n;
int sa[maxn], rank[maxn], height[maxn];
int t[maxn], t2[maxn], c[]; void build_sa(int n, int m)
{
int i, *x = t, *y = t2;
for(i = ; i < m; i++) c[i] = ;
for(i = ; i < n; i++) c[x[i] = s[i]]++;
for(i = ; i < m; i++) c[i] += c[i - ];
for(i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= )
{
int p = ;
for(i = n - k; i < n; i++) y[p++] = i;
for(i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
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];
swap(x, y);
p = ; x[sa[]] = ;
for(i = ; i < n; i++)
x[sa[i]] = y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k] ? p - : p++;
if(p >= n) break;
m = p;
}
} void build_height()
{
int k = ;
for(int i = ; i <= n; i++) rank[sa[i]] = i;
for(int i = ; i < n; i++)
{
if(k) k--;
int j = sa[rank[i] - ];
while(s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
} int d[maxn][]; void init_RMQ()
{
for(int i = ; i < n; i++) d[i][] = height[i + ];
for(int j = ; ( << j) <= n; j++)
for(int i = ; i + ( << j) - < n; i++)
d[i][j] = min(d[i][j-], d[i + (<<(j-))][j-]);
} int RMQ(int L, int R)
{
int k = ;
while( ( << (k+)) <= (R - L + ) ) k++;
return min(d[L][k], d[R-(<<k)+][k]);
} int LCP(int i, int j)
{
i = rank[i] - ; j = rank[j] - ;
if(i > j) swap(i, j);
return RMQ(i + , j);
} int a[maxn], cnt, maxl; int main()
{
//freopen("in.txt", "r", stdin); int kase = ;
while(scanf("%s", s) == && s[] != '#')
{
n = strlen(s);
build_sa(n + , );
build_height();
init_RMQ(); cnt = maxl = ;
for(int i = ; i < n; i++)
{
for(int j = ; j + i < n; j += i)
{
int k = LCP(j, j + i);
int t = k / i + ;
int left = i - (k % i);
int head = j - left;
if(head >= && LCP(head, head + i) >= left) t++;
if(t > maxl)
{
cnt = ;
a[cnt++] = i;
maxl = t;
}
if(t == maxl) a[cnt++] = i;
}
} int len = -, st;
for(int i = ; i <= n && len == -; i++)
{
for(int j = ; j < cnt; j++)
{
int l = a[j];
if(LCP(sa[i], sa[i] + l) >= (maxl - ) * l)
{
len = l;
st = sa[i];
break;
}
}
} printf("Case %d: ", ++kase);
for(int i = ; i < len * maxl; i++) printf("%c", s[st + i]);
puts("");
} return ;
}
代码君
POJ 3693 (后缀数组) Maximum repetition substring的更多相关文章
- poj 3693 后缀数组 重复次数最多的连续重复子串
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8669 Acc ...
- POJ 3693 后缀数组
题目链接:http://poj.org/problem?id=3693 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现在给定一个长度为n的 ...
- [poj 3693]后缀数组+出现次数最多的重复子串
题目链接:http://poj.org/problem?id=3693 枚举长度L,看长度为L的子串最多能重复出现几次,首先,能出现1次是肯定的,然后看是否能出现两次及以上.由抽屉原理,这个子串出现次 ...
- POJ - 2406 ~SPOJ - REPEATS~POJ - 3693 后缀数组求解重复字串问题
POJ - 2406 题意: 给出一个字符串,要把它写成(x)n的形式,问n的最大值. 这题是求整个串的重复次数,不是重复最多次数的字串 这题很容易想到用KMP求最小循环节就没了,但是后缀数组也能写 ...
- POJ 3693 后缀数组+RMQ
思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...
- POJ3693 Maximum repetition substring 后缀数组
POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- POJ 3693 Maximum repetition substring(最多重复次数的子串)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10461 Ac ...
- Maximum repetition substring 后缀数组
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7578 Acc ...
随机推荐
- CSS自定义select下拉选择框(不用其他标签模拟)
今天群里有人问到怎么自定义select下拉选择框的样式,于是群里就展开了激烈的讨论,刚开始一直就是考虑怎样使用纯CSS实现,把浏览器默认的样式覆盖掉,但最后均因兼容问题处理不好而失败告终,最后的解决方 ...
- URL编码方法比较
javascript中存在几种对URL字符串进行编码的方法:escape(),encodeURI(),以及encodeURIComponent().这几种编码所起的作用各不相同. escape() 方 ...
- javascript设计模式-迭代器模式(Iterator)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Unity bundle的制作和使用
原地址:http://unity3d.9ria.com/?p=2863 Unity有个很好的功能,大致是很多专注于PC的engine没有提供的(因为没有必要),就是能加载主包外的资源,这个主包外的资源 ...
- 云计算中iaas、paas、saas的区别和联系
概念: iass : Infrastructure(基础设施)-as-a-Service, paas : Platform(平台)-as-a-Service, saas : Software(软件)- ...
- Jmeter测试Mysql
一.在测试计划下,找到Add directory or jar to classpath下填入jdbc驱动路径. 二.新建线程组. 三.在线程组下,添加配置元件—JDBC Connection Con ...
- Set Matrix Zeroes
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click ...
- 社交APP经典死法18种,听野路子产品菜狗怎么说
点这里 社交APP经典死法18种,听野路子产品菜狗怎么说 时间 2015-04-06 11:24:53 虎嗅网相似文章 (4)原文 http://www.huxiu.com/article/112 ...
- pku 1703(种类并查集)
题目链接:http://poj.org/problem?id=1703 思路;个人觉得本质上还是和带权并查集一样的,只不过多了一个MOD操作,然后就是向量关系图稍微改动一下就变成种类并查集了,对于本题 ...
- appium自动化测试中获取toast消息的解决方法【转】
http://blog.csdn.net/hqzxsc2006/article/details/50036911 待实践.. 解决方法:appium下切换selendroid模式去获取Android的 ...