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 ...
随机推荐
- 5.7 Nginx 其他模块
- C# 篇基础知识1——编译、进制转换、内存单位、变量
编译:C#语言要经过两次编译,程序员编写好源代码后进行第一次编译,将源代码编译为微软中间语言(MSIL),生成可以发布的应用软件:当用户使用软件时,MSIL代码会在首次载入内存后进行第二次编译,中间语 ...
- 2.Jsoup
public static void main(String[] args) { //爬取最大资源网上的数据 //用CSS选择器 try { Document doc = Jsoup.parse(ne ...
- 1_01_MSSQL课程_基础入门2
1.数据库的迁移方案 ->分离 附加 ->权限问题: ->启用Administrator账号 ->把数据库文件放到默认的数据库文件存放目录. ->数据库文件兼容级别,设置 ...
- 设备树DTS 学习:3-常用的DTS 函数
Linux内核中目前DTS相关的函数都是以of_前缀开头的,它们的实现位于内核源码的drivers/of下面 void __iomem*of_iomap(struct device_node *nod ...
- YOLO V1、V2、V3算法 精要解说
前言 之前无论是传统目标检测,还是RCNN,亦或是SPP NET,Faste Rcnn,Faster Rcnn,都是二阶段目标检测方法,即分为“定位目标区域”与“检测目标”两步,而YOLO V1,V2 ...
- Phoenix与HBase集成进行数据分析
安装好Phoenix后配置环境变量 export PHOENIX_PATH=/opt/cloudera/parcels/APACHE_PHOENIX-4.14.0-cdh5.14.2.p0.3expo ...
- 新手小白如何向GitHub上提交项目
首先你得注册一个自己的GitHub账号,注册网址:https://github.com/join 创建一个新的项目,填写项目名称,描述 创建完成之后,跳转到下面的页面,下面红框中的网址要记住,在后面上 ...
- 文本处理三剑客与shell正则表达式
文本处理三剑客 提到对于文本的处理上,除了vim这个强大的编辑器之外,还有使用命令的形式去处理你要处理的文本,而不需要手动打开文本再去编辑.这样做的好处是能够以shell命令的形式将编辑和处理文本的工 ...
- java执行操作系统脚本
http://www.cnblogs.com/bencakes/p/6139477.html 以前只是知道Runtime.getRuntime().exec(command);这种用法,但是有时候命令 ...