找重复次数最多的字串,如果有多解,要求字典序最小。

我也是跟着罗穗骞菊苣的论文才刷这道题的。

首先还是枚举一个循环节的长度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的更多相关文章

  1. poj 3693 后缀数组 重复次数最多的连续重复子串

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

  2. POJ 3693 后缀数组

    题目链接:http://poj.org/problem?id=3693 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现在给定一个长度为n的 ...

  3. [poj 3693]后缀数组+出现次数最多的重复子串

    题目链接:http://poj.org/problem?id=3693 枚举长度L,看长度为L的子串最多能重复出现几次,首先,能出现1次是肯定的,然后看是否能出现两次及以上.由抽屉原理,这个子串出现次 ...

  4. POJ - 2406 ~SPOJ - REPEATS~POJ - 3693 后缀数组求解重复字串问题

    POJ - 2406 题意: 给出一个字符串,要把它写成(x)n的形式,问n的最大值. 这题是求整个串的重复次数,不是重复最多次数的字串 这题很容易想到用KMP求最小循环节就没了,但是后缀数组也能写 ...

  5. POJ 3693 后缀数组+RMQ

    思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...

  6. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

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

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

  8. POJ 3693 Maximum repetition substring(最多重复次数的子串)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10461   Ac ...

  9. Maximum repetition substring 后缀数组

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

随机推荐

  1. xmlns与targetNamespace

    xmlns与targetNamespace xmlns与targetNamespacehttp://blog.sina.com.cn/weatry在使用XML Schema生成XML文件时,我们常常会 ...

  2. java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

    org.springframework.dao.TransientDataAccessResourceException: ### Error updating database. Cause: ja ...

  3. 表单很多数据项录入的时候,提交controller发生异常,数据回显。

    1.添加的情况(Model传递Form Data) request.getSession().setAttribute("car", car); //抛出异常的时候,数据回显. 2 ...

  4. iOS第三方推送-极光推送

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  5. Linux下进程通信的八种方法

    Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...

  6. mvc5 知识点01

    1.ViewBag 动态数据类型,也就是说可以随便指定属性,前后台传值很是有用 2.Layout 属性,定义模版,模版中一般用@RenderBody() 做占位符,用于放置子页面内容 3.@model ...

  7. Edius 安装 looks插件整理

    需要安装looks插件到指定目录,在后面桥接时选择该目录. 包括安装looksbuilder插件.

  8. Linux Command Line 解析

    Linux Command Line 解析 0 处理模型 Linux kernel的启动包括很多组件的初始化和相关配置,这些配置参数一般是通过command line进行配置的.在进行后续分析之前,先 ...

  9. 图解TCP/IP读书笔记(二)

    图解TCP/IP读书笔记(二) 第二章.TCP/IP基础知识 一.TCP/IP出现的背景及其历史 年份 事件 20世纪60年代后半叶 应DoD(美国国防部)要求,美国开始进行通信技术相关的研发 196 ...

  10. Echarts事件

    Echart饼图.柱状图.折线图(pie.bar.line)添加点击事件发布日期:2014年08月10日   来源:PHP1.CN     点击:250638摘要:var myChart= echar ...