Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)
The repetition number of a string is defined as the maximum number \(R\) such that the string can be partitioned into \(R\) same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.
Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.
Input
The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.
The last test case is followed by a line containing a '#'.
Output
For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.
Sample Input
ccabababc
daabbccaa
#
Sample Output
Case 1: ababab
Case 2: aa
题意:
找出原字符串中的重复次数最多的连续重复子串。
题解:
记这个连续重复子串为\(L\),我们可以发现,这个字符串一定会覆盖\(s[0],s[L],s[L*2]\).....这些点中相邻的两个(因为长度至少为\(2L\)嘛)。假设它覆盖的是\(s[L*i]\)和\(s[L*(i+1)]\),那么我们就往前和往后计算能匹配多远(往后匹配用到了后缀数组的height数组,往前匹配可以while到\(s[L*(i-1)]\),越过\(s[L*(i-1)]\)的情况和前面计算的重复了,可以不算)
记往前匹配和往后匹配的最长长度为k,则重复次数为\(k/L+1\)。
再求lcp的时候用st表优化一下即可
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
char s[N];
int n;
int fir[N],sec[N],rnk[N],t[N],sa[N],b[N];
double log2(double x){
return log(x)/log(2.0);
}
void msort(){
memset(t,0,sizeof t);
for(int i=1;i<=n;++i)t[sec[i]]++;
for(int i=1;i<N;++i)t[i]+=t[i-1];
for(int i=n;i;--i)b[t[sec[i]]--]=i;
memset(t,0,sizeof t);
for(int i=1;i<=n;++i)t[fir[b[i]]]++;
for(int i=1;i<N;++i)t[i]+=t[i-1];
for(int i=n;i;--i)sa[t[fir[b[i]]]--]=b[i];
}
int height[N];
void get_height(char *s){
int k=0;
for(int i=1;i<=n;++i){
if(rnk[i]==1){
height[i]=0;
continue;
}
if(k)--k;
int j=sa[rnk[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
height[i]=k;
}
}
int mn[N][20];
void get_height_st(){
for(int i=1;i<=n;++i)mn[i][0]=height[sa[i]];
int t=log2(n);
for(int i=1;i<=t;++i){
for(int j=1;j<=n;++j){
if(j+(1<<(i-1))>n)mn[j][i]=mn[j][i-1];
else mn[j][i]=min(mn[j][i-1],mn[j+(1<<(i-1))][i-1]);
}
}
}
int height_query(int l,int r){
l=rnk[l],r=rnk[r];
if(l>r)swap(l,r);l++;
int t=log2(r-l+1);
return min(mn[l][t],mn[r-(1<<t)+1][t]);
}
void get_sa(char *s){
for(int i=1;i<=n;++i)rnk[i]=s[i];
for(int k=1;k<=n;k*=2){
for(int i=1;i<=n;++i){
fir[i]=rnk[i];
if(i+k>n)sec[i]=0;
else sec[i]=rnk[i+k];
}
msort();
int num=1;rnk[sa[1]]=1;
for(int i=2;i<=n;++i){
if(fir[sa[i]]!=fir[sa[i-1]]||sec[sa[i]]!=sec[sa[i-1]])num++;
rnk[sa[i]]=num;
}
if(num==n)break;
}
}
int maxn,pos,len;
void find(){
maxn=1;
for(int i=1;i<=n/2;++i){
for(int j=1;j+i<=n;j+=i){
if(s[j]!=s[j+i])continue;
int k=height_query(j,j+i),now,r;
now=k/i+1,r=i-k%i;
int cnt=0,p=j;
for(int m=j-1;m>j-i&&s[m]==s[m+i]&&m;--m){
cnt++;
if(cnt==r)now++,p=m;
else p=rnk[p]>rnk[m]?m:p;
}
if(now>maxn)maxn=now,pos=p,len=i;
else if(now==maxn&&rnk[pos]>rnk[p])pos=p,len=i;
}
}
}
int main(){
int js=0;
while(1){
js++;
cin>>s+1;
if(s[1]=='#')break;
n=strlen(s+1);
get_sa(s);
get_height(s);
get_height_st();
find();
printf("Case %d: ",js);
for(int i=pos;i<=pos+len*maxn-1;++i){
putchar(s[i]);
}puts("");
}
}
Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)的更多相关文章
- Maximum repetition substring POJ - 3693(重复次数最多的连续重复子串)
这题和SPOJ - REPEATS 一样 代码改一下就好了 这个题是求这个重复子串,还得保证字典序最小 巧妙运用sa 看这个 https://blog.csdn.net/queuelovestack ...
- POJ 3693 Maximum repetition substring(后缀数组+ST表)
[题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...
- SPOJ 687 Repeats(后缀数组+ST表)
[题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...
- BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay
BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...
- UVA10829 L-Gap Substrings(后缀数组+ST表)
后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分
4310: 跳蚤 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 180 Solved: 83[Submit][Status][Discuss] De ...
- URAL 1297 Palindrome(后缀数组+ST表)
[题目链接] http://acm.timus.ru/problem.aspx?num=1297 [题目大意] 求最长回文子串,并输出这个串. [题解] 我们将原串倒置得到一个新的串,加一个拼接符将新 ...
- UVA 11475 Extend to Palindrome(后缀数组+ST表)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...
随机推荐
- 【51NOD】1006 最长公共子序列Lcs(动态规划)
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个 ...
- sql相同项求和
select (SELECT O2.ORG_NAME FROM OUTSOURCE_ORG O2 where o2.org_id = oo.parent_id) ...
- python里面的数学
一.基本运算符 1.算数运算 2.比较运算 特殊情况:!= 不等于 新版本不支持 <> 不等号 3.赋值运算 4.逻辑运算 not : 非 非真即假,非假即真. - and : 并 ...
- C#装箱,拆箱和强制转换(转)
出处:https://www.cnblogs.com/fengjiulin110120/p/6605739.html 关系: 强制转换就包含有装箱拆箱操作,装箱就是把值类型转换成引用类型,反之就是拆箱 ...
- C# Bitmap长宽参数构造的图片对象的每个像素ARGB都是0
var img = new Bitmap(100 , 100); for (int i = 0; i < img.Width; i++) { for (int j = 0; j < i ...
- related work
Traditional approaches, e.g., genetic algorithm (GA) [2] and ant colony optimization (ACO) [3], can ...
- BZOJ 1029 [JSOI2007]建筑抢修 (贪心 + 优先队列)
1029: [JSOI2007]建筑抢修 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 5452 Solved: 2422[Submit][Statu ...
- querySelectorAll()方法
querySelectorAll()方法 调用的对象包括:Document(文档) DocumentFragment(文档片段) Element(元素) querySelectorAll()方法接收的 ...
- Typecho 插件开发基础
<?php /** * 标题 插件说明 * * @package 添加标题 * @author Fan * @version 1.0.0 * @link http://cnblogs.com/f ...
- referraluserid推广ID号跟踪JS处理A标签
网站推广ID号跟踪 xxx.html?referraluserid=123 referraluserid.js JS源文件 referraluserid的参数会自动绑定页面A标签 有时是Post 表单 ...