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 ...
随机推荐
- 「NOIP2013」华容道
传送门 Luogu 解题思路 预支一点东西: 这题其实有着更为思维的图模型,还十分考验码力,不简单啊 这居然是联赛题 讲正解: 显然我们对于一种合法方案,空格子肯定是一直围绕着特定棋子反复横跳的. 所 ...
- MyBatis Dao层的编写
传统的dao层编写 以前编写dao层,先新建一个包com.chy.dao,再写接口StudentDao: public interface StudentDao { public void inser ...
- Java安全中的“大坑”,跨平台真“浮云”
Java安全HttpDB 最近在做一个开源项目HttpDB,它的目标是在互联网中通过JDBC安全的查询数据库,解决云计算报表的数据库访问问题. 数据传输使用AES加密算法,用到了Java提供的安全库j ...
- 二 SVN代码冲突的解决
问题: A和B都是最新的代码,A修改了代码提交了,B也修改了代码,但是B提交的时候出现冲突的问题. 解决方案:编辑冲突 解决冲突: 方法一:将文件里面冲突的描述去掉,重新提交 方法二:软件解决冲突
- 51nod 1765 谷歌的恐龙
一开始看到了期望吓半死..然后弱弱的写了一下式子.设∑是出去m项之后的和,∑' 是m项的和. E=(n/m)*(∑'/m)+(n/m)*((n-m)/n)*(∑'/m+∑/(n-m))+(n/m)*( ...
- other#apache-commons
if you want to be a better javaer, you should spent time on apache commons.
- [Codeforces] #603 (Div. 2) A-E题解
[Codeforces]1263A Sweet Problem [Codeforces]1263B PIN Code [Codeforces]1263C Everyone is a Winner! [ ...
- 爬虫(十六):Scrapy框架(三) Spider Middleware、Item Pipeline
1. Spider Middleware Spider Middleware是介入到Scrapy的Spider处理机制的钩子框架. 当Downloader生成Response之后,Response会被 ...
- win2008R2 局域网共享
1.解决windows server 2008 R2 不能开启网络发现 开始–>管理工具–>服务,以下3个服务选择自动.开启: Function Discovery Resource Pu ...
- cf 543 D. Road Improvement
(懒得想了,,又是DP) #include<bits/stdc++.h> #define N 200005 #define LL long long #define inf 0x3f3f3 ...