poj 3693 Maximum repetition substring
呵呵呵呵呵呵呵呵呵呵,sb(神犇)题看了一天,还是不懂
题目要求的是最多重复的,那么就来找重复的,可以先枚举一个重复的单元(比如ababab,就枚举ab)的长度,
然后再原串中,会有ch[0],ch[L],c[2*L],,,,,这些,如果重复的话肯定是会有ch[i*L]==ch[(i+1)*L]的,那么我们枚举这个东西。
在找到之后,需要做的就是找ch[(i+1)*L]之后可以有多长重复 L1,以及ch[i*L]之前有多少重复 L2,这个问题用后缀数组的height处理出的RMQ解决(呵呵呵),这一步貌似是叫求两个后缀的最长公共前缀。。。(对余ch[i*L]往前的,就把串反过来搞),然后答案就是(L1+L2)/L+1。
然而这个恶心题还要求最小字典序。。。。那么考虑,另外寻找重复部分的开头,我们知道,已经找出了重复串的长度,那么在这里面的任意位置都是满足重复这个性质的,所以考虑(L1+L2)%L(长度不及L的部分,可以画图看一下),然后在搞一个ST表来记录区间的rank,然后在 i*L-L2 到 i*L-L2+(L1+L2)%L查询最小的rank就好。。
(本蒟蒻就会这么多,大神勿喷2333)
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 100005
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
int n,mx,ans,ansl,ansr;
int bin[],Log[];
int mn[][];
char ch[];
void rmq(int mn[N][], int *a)
{
for (int i=; i<=n; i++) mn[i][]=a[i];
for (int i=; i<=Log[n]; i++)
for (int j=; j<=n; j++)
if (j+bin[i]-<=n)
mn[j][i]=min(mn[j][i-],mn[j+bin[i-]][i-]);
else break;
}
struct Suffix{
int k,p,q;
int rk[][N],sa[][N],v[N],a[N];
int h[N],mn[N][];
void clear()
{
memset(a,,sizeof(a));
memset(v,,sizeof(v));
memset(rk,,sizeof(rk));
}
void cal_sa(int *sa, int *rk, int *SA, int *RK)
{
for (int i=; i<=n; i++) v[rk[sa[i]]]=i;
for (int i=n; i>=; i--)
if (sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;
for (int i=n-k+; i<=n; i++) SA[v[rk[i]]--]=i;
for (int i=; i<=n; i++)
RK[SA[i]]=RK[SA[i-]]+(rk[SA[i-]]!=rk[SA[i]] || rk[SA[i-]+k]!=rk[SA[i]+k]);
}
void get_sa()
{
p=,q=;
for (int i=; i<=n; i++) v[a[i]]++;
for (int i=; i<=; i++) v[i]+=v[i-];
for (int i=; i<=n; i++) sa[p][v[a[i]]--]=i;
for (int i=; i<=n; i++)
rk[p][sa[p][i]]=rk[p][sa[p][i-]]+(a[sa[p][i]]!=a[sa[p][i-]]);
for (k=; k<n; k<<=,swap(p,q)) cal_sa(sa[p],rk[p],sa[q],rk[q]);
}
void get_height()
{
k=;
for (int i=; i<=n; i++)
{
if (rk[p][i]==) h[]=;
else{
int j=sa[p][rk[p][i]-];
while (a[i+k]==a[j+k]) k++;
h[rk[p][i]]=k;
if (k>) k--;
}
}
}
void pre()
{
get_sa(); get_height(); rmq(mn,h);
}
int lcp(int x, int y)
{
x=rk[p][x],y=rk[p][y];
if (x>y) swap(x,y);
x++;
int t=Log[y-x+];
return min(mn[x][t],mn[y-bin[t]+][t]);
}
}c[];
int query(int x, int y)
{
int t=Log[y-x+];
return min(mn[x][t],mn[y-bin[t]+][t]);
}
void solve(int L)
{
int l=,r=,t;
for (int i=; i+L<=n; i+=L)
if (ch[i]==ch[i+L])
{
r=c[].lcp(i,i+L),l=c[].lcp(n-i+,n-i-L+);
if ((l+r)/L+>mx)
mx=(l+r)/L+,ans=inf;
if ((l+r)/L+==mx)
{
t=query(i-l,i-l+(l+r)%L);
if (t<ans)
{
ans=t;
ansl=c[].sa[c[].p][t],ansr=ansl+mx*L-;
}
}
}
}
int main()
{
bin[]=; for (int i=; i<=; i++) bin[i]=bin[i-]<<;
Log[]=-; for (int i=; i<=; i++) Log[i]=Log[i/]+;
int txt=;
while (scanf("%s",ch+))
{
if (ch[]=='#') break;
printf("Case %d: ",++txt);
c[].clear(); c[].clear();
n=strlen(ch+);
for (int i=; i<=n; i++) c[].a[i]=ch[i]-'a'+;
for (int i=; i<=n; i++) c[].a[i]=ch[n-i+]-'a'+;
c[].pre(); c[].pre();
rmq(mn,c[].rk[c[].p]);
mx=; ans=inf;
for (int i=; i<=n; i++)
if (c[].rk[c[].p][i]<ans)
ans=c[].rk[c[].p][i],ansl=ansr=i;
for (int i=; i<=n; i++) solve(i);
for (int i=ansl; i<=ansr; i++)
putchar(ch[i]);
puts("");
}
return ;
}
poj 3693 Maximum repetition substring的更多相关文章
- POJ 3693 Maximum repetition substring(最多重复次数的子串)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10461 Ac ...
- POJ 3693 Maximum repetition substring(后缀数组)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)
传送门:POJ - 3693 题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...
- POJ 3693 Maximum repetition substring(后缀数组+ST表)
[题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...
- POJ 3693 Maximum repetition substring(连续重复子串)
http://poj.org/problem?id=3693 题意:给定一个字符串,求重复次数最多的连续重复子串. 思路: 这道题确实是搞了很久,首先枚举连续子串的长度L,那么子串肯定包含了r[k], ...
- 后缀数组 POJ 3693 Maximum repetition substring
题目链接 题意:给定一个字符串,求重复次数最多的连续重复子串. 分析:(论文上的分析)先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次.首先连续出现 1 次是肯定可以的,所以这里只考虑至少 ...
- poj 3693 Maximum repetition substring (后缀数组)
其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...
- POJ 3693 Maximum repetition substring (后缀数组+RMQ)
题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...
- poj 3693 Maximum repetition substring 重复次数最多的连续子串
题目链接 题意 对于任意的字符串,定义它的 重复次数 为:它最多可被划分成的完全相同的子串个数.例如:ababab 的重复次数为3,ababa 的重复次数为1. 现给定一字符串,求它的一个子串,其重复 ...
- POJ 3693 Maximum repetition substring ——后缀数组
重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...
随机推荐
- 「CF741D」Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
传送门 Luogu 解题思路 考虑把22个字符状压下来,易知合法情况就是状态中之多有一个1,这个可以暴力一点判断23次. 然后后就是 dsu on the tree 了. 细节注意事项 咕咕咕 参考代 ...
- python2中新式类和经典类的多重继承调用顺序
class A: def foo(self): print('called A.foo()') class B(A): pass class C(A): def foo(self): print('c ...
- 说说我对SQL语句执行顺序的理解,以SQL Server为例
有人说SQL语句难学,其实并不难!只要掌握了基本的语句执行顺序,用程序化的思维分析结构,再难的问题也会迎刃而解! 假设有如下表emp 现在要求 列出员工姓名(ename)中不含A的所有人按照部门编号( ...
- Eclipse设置自动提示代码(不用alt+/了)
在preferences找到如图的相关位置.在输入框里把26个字母加进去,qwer...........
- D - Recommendations
就是有n组,每组的数量是num,只能增加数字,增加的代价为t,求能使所有组的数量都不同的最小代价. #include<bits/stdc++.h> #define N 200005 #de ...
- iOS 十种线程锁
锁 是什么意思? 我们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题,这时候就需要我们保证每次只有一个线程访问这一块资源,锁 应运而生. 这里顺便提一下,上锁 ...
- spring-boot-autoconfigure-xx.jar核心注解
- 027、MySQL字符串替换函数,文本替换函数,字符串填充函数
#文本填充 ,'); #ABC12121212121212121 #文本替换 SELECT REPLACE('田攀520','攀','ABC'); #田ABC520 不忘初心,如果您认为这篇文章有价值 ...
- 删除C代码中的注释行【状态机】
今天在学ruby时遇到的一个经典的题目,一直都知道但从来没有实现过.呈上状态机,代码略.(写代码的时候还是需要注意一些小情况的)
- python中numpy矩阵运算操作大全(非常全)!
python中numpy矩阵运算操作大全(非常全) //2019.07.10晚python矩阵运算大全1.矩阵的输出形式:对于任何一个矩阵,python输出的模板是:import numpy as n ...