POJ3693 Maximum repetition substring 后缀数组
POJ - 3693 Maximum repetition substring
题意
输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的
Sample input
ccabababc
daabbccaa
#
Sample Output
Case 1: ababab
Case 2: aa
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5+;
char s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn];
int n;
//构造字符串s的后缀数组, 每个字符值必须为0 ~ m-1
void build_sa(int m) {
int *x = t, *y = t2;
//基数排序
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 p = ;
//直接利用sa数组排序第二关键字
for(int i = n-k; i < n; i++) y[p++] = i;
for(int i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
//基数排序第一关键字
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[y[i]]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i>= ; i--) sa[--c[x[y[i]]]] = y[i];
//根据sa和y数组计算新的x数组
swap(x, y);
p = ;
x[sa[]] = ;
for(int 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;
}
} int rank_[maxn]; //rank[i]代表后缀i在sa数组中的下标
int height[maxn]; //height[i] 定义为sa[i-1] 和 sa[i] 的最长公共前缀
//后缀j和k的LCP长度等于RMQ(height, rank[j]+1, rank[k])
void get_height() {
int i, j, k = ;
for(int i = ; i < n; i++) rank_[sa[i]] = i;
for(int i = ; i < n; i++) {
if(!rank_[i]) continue;
int j = sa[rank_[i]-];
if(k) k--; while(s[i+k] == s[j+k]) k++;
height[rank_[i]] = k;
}
}
int d[maxn][];
void rmq_init() {
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) {
if(l == r) return n-l;
if(rank_[l] > rank_[r]) swap(l, r);
int L = rank_[l]+;
int R = rank_[r];
int k = ;
while((<<(k+)) <= R-L+) k++;
return min(d[L][k], d[R-(<<k)+][k]);
} int a[maxn];
int main() {
int kase = ;
while(~scanf("%s", s) && s[] != '#') {
int L = strlen(s);
n = L + ;
build_sa();
get_height();
rmq_init();
int mx = ;
int cnt = ;
// 寻找重复次数最多的连续子串单个子串的长度,可能有多种重复次数相同的子串
for(int l = ; l <= L; l++) {
for(int j = ; j + l < L; j += l) {
int k = rmq(j, j + l); // lcp
int res = k / l + ;
int pos = j - (l - (k % l));
if(pos >= && k % l && rmq(pos, pos + l)) res++;
if(res > mx) {
mx = res;
cnt = ;
a[cnt++] = l;
} else if(res == mx) {
a[cnt++] = l;
}
}
}
// 找字典序最小
int len = , st;
for(int i = ; i < n && !len; i++) {
for(int j = ; j < cnt; j++) {
if(rmq(sa[i], sa[i] + a[j]) >= (mx - ) * a[j]) {
len = a[j];
st = sa[i];
break;
}
}
}
printf("Case %d: ", ++kase);
for(int i = st; i < st + len * mx; i++) {
printf("%c", s[i]);
}
printf("\n");
}
return ;
}
POJ3693 Maximum repetition substring 后缀数组的更多相关文章
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- poj3693 Maximum repetition substring (后缀数组+rmq)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- Maximum repetition substring 后缀数组
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7578 Acc ...
- POJ 3693 Maximum repetition substring ——后缀数组
重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...
- 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串
POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...
- poj 3693 Maximum repetition substring (后缀数组)
其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...
- POJ 3693 Maximum repetition substring (后缀数组+RMQ)
题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...
- poj3693 Maximum repetition substring
题意 给出一个长度为\(n(n\leqslant 100000)\)的串,求一个字典序最小的子串使得它是某个字符串重复\(k\)次得到的,且\(k\)最大 题解 后缀数组论文上的题,跟上一篇uva那个 ...
随机推荐
- async,await与task.wait()或task.Result的区别
你是否曾经与我一样不理解async,await与task.wait()或者task.Result的区别? 接下来,一个Demo让你看出他们之间的区别. static void Main(string[ ...
- 笔记-VUE滚动加载更多数据
来源:https://blog.csdn.net/qq_17281881/article/details/87342403 VUE滚动加载更多数据 data() { return { loading: ...
- 解释BOM头和去掉方法
http://www.thinkphp.cn/topic/2592.html 以上是叫你去掉bom头的,因为有些文件加载不出来就是window会以记事本的形式打开,然后默认给我们加了了bom头,有些文 ...
- qt 鼠标拖动窗口 跳动 解决
因为获取当前的位置,似乎没有把标题栏的高度记进去. 所以移动前,得考虑到标题栏的高度. 用以下方式获取标题栏高度: QApplication::style()->pixelMetric(QSty ...
- Spring Security OAuth2 笔记(一)
关于 refresh_token refresh_token 主要是用来在 access_token 快要过期的时候,对 access_token 进行一个刷新,生成一个新的 access_token ...
- Session服务器之Redis
Session服务器之Redis Redis与Memcached的区别内存利用率:使用简单的key value (键值对)存储的话,Mermcached 的内存利用率更高,而如果Redis采用hash ...
- Micropython教程之TPYBoard开发板驱动舵机教程(萝卜学科编程教育)
大家应该都看到过机器人的手臂啊腿脚啊什么的一抽一抽的在动弹吧...是不是和机械舞一样的有节奏,现在很多机器人模型里面的动力器件都是舵机. 但是大家一般见到的动力器件都是像步进电机,直流电机这一类的动力 ...
- React Native中自定义导航条
这是2017年年初开始的公司的项目,对于导航条的要求很高,Android和iOS上必须用一致的UI,按钮位置还有各种颜色都有要求,而且要适应各种奇葩要求. 尝试了一下当时React Native自带的 ...
- 2016年全球IC设计大厂营收排名:高通稳居龙头
TrendForce旗下拓墣产业研究所最新研究统计,2016年全球前十大无晶圆IC设计业者营收中,高通(QCT)仍然稳居龙头宝座.而前三大业者高通.新博通(Broadcom)与联发科合计营收占前十名营 ...
- Linked List-2
三.编码技巧 1.遍历链表 先将head指针赋值给一个局部变量current: //return the number of nodes in a list (while-loop version) ...