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 后缀数组的更多相关文章

  1. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

  2. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  3. poj3693 Maximum repetition substring (后缀数组+rmq)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

  4. Maximum repetition substring 后缀数组

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7578   Acc ...

  5. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

  6. 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串

    POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...

  7. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  8. POJ 3693 Maximum repetition substring (后缀数组+RMQ)

    题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...

  9. poj3693 Maximum repetition substring

    题意 给出一个长度为\(n(n\leqslant 100000)\)的串,求一个字典序最小的子串使得它是某个字符串重复\(k\)次得到的,且\(k\)最大 题解 后缀数组论文上的题,跟上一篇uva那个 ...

随机推荐

  1. Android | 教你如何快速集成机器学习能力

    背景   继上篇博文说了如何快速集成扫码以后 我又上官网去了解了一下其他的功能,其中机器学习服务是当下比较火的,而且还是免费的.就赶紧点进去学习一下.看看能够快速实现哪些功能. 链接在这里:https ...

  2. vue2.x学习笔记(二十八)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12682573.html. 生产环境部署 以下大多数内容在你使用vue cli的时候都是默认开启的,仅跟你自定义的构 ...

  3. Ubuntu登陆时忘记密码怎么办

    有时候由于各种原因,用户会忘记自己登陆Ubuntu的登陆密码,这个时候我们能怎么办呢? 第一步:先重启电脑,开机时长按shift键,进入grub菜单: 第二步:按“e”键编辑启动项,显示如下图,将下图 ...

  4. css套路学习(一)

    css3信息获取方法 文档搜索:Google css spec; Google: 关键词 MDN; css tricks成熟css代码块sinppets; Google: center css tri ...

  5. Boostrap Table学习笔记

    最近要对项目上的table进行调整,让表格能够支持更多的操作,于是接触到了boostrapTable这个插件.研究了一天,记录下学习的内容. Boostrap Table可以支持表的分页及动态显示表的 ...

  6. C语言编程入门题目--No.14

    题目:将一个正整数分解质因数.例如:输入90,打印出90=233*5. 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: (1)如果这个质数恰等于n,则说明分解质因数的过程 ...

  7. 数学--数论--POJ 1061青蛙的约会 (扩展欧几里得算法)

    青蛙的约会 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问 ...

  8. The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)

    This is an era of team success, but also an era of heroes. Throughout the ages, there have been nume ...

  9. python http server handle json

    用Python实现一个http server # python2 # coding = utf-8 from BaseHTTPServer import HTTPServer, BaseHTTPReq ...

  10. 1年之后的拿高工资的资本,Java线程

    只要开启线程,都会开启一块对应的栈内存,然后进行同步执行. -- 谈斌 线程是CPU用来处理程序的资源,线程的执行是抢占式的. 线程开启方式: 创建一个类,继承Thread类.重写 run(), 并在 ...