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 ...
随机推荐
- 092、Java中String类之字符串内容比较
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- Sqlserver 基本面试题
一 单词解释(2分/个) 34分 Data 数据 Database 数据库 RDBMS 关系数据库管理系统 GRANT 授权 REVOKE 取消权限 DENY 拒绝权限 DECLARE 定义变量 PR ...
- aforge视频录像,对界面进行重绘
由于项目需要,需要录像的时候在界面加多一个圆圈,并且一起录制下来. 只需要在NewFrame增加以下代码 private void videoSourcePlayer1_NewFrame(object ...
- 第3节 sqoop:7、通过java代码远程连接linux执行shell命令
数据库的数据同步软件sqoop 数据同步 关系型数据库到大数据平台 任务:sqoop 是批量导入数据太慢,如何做到实时的数据同步 实时的数据同步工具: canal 阿里开源的一个数据库数据实时同步的软 ...
- 024、Java中字符串连接字符串拼接
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- 001-PHP静态变量
<?php function ADD1() { static $a = 10; //定义静态变量 $a += 1; echo "静态变量a的值为:" . $a . " ...
- Java 用户输入
章节 Java 基础 Java 简介 Java 环境搭建 Java 基本语法 Java 注释 Java 变量 Java 数据类型 Java 字符串 Java 类型转换 Java 运算符 Java 字符 ...
- ACM-小偷的背包
题目描述:小偷的背包 设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,...,wn.问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S.如果有满足条 ...
- POJ 3614:Sunscreen 贪心+优先队列
Sunscreen Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5378 Accepted: 1864 Descrip ...
- mariadb galera启动问题
搭建了mariadb galera集群后,整个集群停掉后如何启动呢,我们要先启动那个节点呢,今天我尝试把集群机器全部停掉,然后任意启动一个节点,发现报如下的错误: 170620 21:32:55 [E ...