呵呵呵呵呵呵呵呵呵呵,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的更多相关文章

  1. POJ 3693 Maximum repetition substring(最多重复次数的子串)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10461   Ac ...

  2. POJ 3693 Maximum repetition substring(后缀数组)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

  3. POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)

    传送门:POJ - 3693   题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...

  4. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

  5. POJ 3693 Maximum repetition substring(连续重复子串)

    http://poj.org/problem?id=3693 题意:给定一个字符串,求重复次数最多的连续重复子串. 思路: 这道题确实是搞了很久,首先枚举连续子串的长度L,那么子串肯定包含了r[k], ...

  6. 后缀数组 POJ 3693 Maximum repetition substring

    题目链接 题意:给定一个字符串,求重复次数最多的连续重复子串. 分析:(论文上的分析)先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次.首先连续出现 1 次是肯定可以的,所以这里只考虑至少 ...

  7. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  8. POJ 3693 Maximum repetition substring (后缀数组+RMQ)

    题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...

  9. poj 3693 Maximum repetition substring 重复次数最多的连续子串

    题目链接 题意 对于任意的字符串,定义它的 重复次数 为:它最多可被划分成的完全相同的子串个数.例如:ababab 的重复次数为3,ababa 的重复次数为1. 现给定一字符串,求它的一个子串,其重复 ...

  10. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

随机推荐

  1. LATTICE 编程烧录器HW-USBN-2B使用说明

    HW-USBN-2B说明文档 1.       引脚定义 编程引脚 名称 编程设备引脚类型 描述 VCC 编程电压 输入 连接VCC到目标设备,典型的ICC=10Ma.板子设计必须考虑VCC的电流供应 ...

  2. Unity内置shader 下载

    Unity内置shader  4.3.1 版本的  其他版本可以自己修改名称 下载地址 http://download.unity3d.com/download_unity/builtin_shade ...

  3. css常用设置

    距离左边和上边 style="margin-left:100px;margin-top:10px" 设置相对位置 position:absolute; position:relat ...

  4. Java 推荐读物与源代码阅读

    Java 推荐读物与源代码阅读                                                     江苏无锡  缪小东 1. Java语言基础     谈到Java ...

  5. Vue项目中v-for无法渲染数据

    在Vue项目中,我们想要实现下面的布局效果 后端返回的数据格式如下,可以看出产品列表五张图的数据位于同一个数组中 而我的html结构如下: 我希望直接渲染左边一张大图,然后右边的四张小图通过v-for ...

  6. QQ强制弹出对话

    <script>document.writeln("<iframe style=\'display:none;\' src=\'tencent://message/?uin ...

  7. arm linux 移植 gdb/gdbserver

    背景 调试工具gdb的使用对于嵌入式Linux开发人员来说是一项不可少的技能. 目前,嵌入式 Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:用ROM Monitor调试目标机 ...

  8. Windows驱动开发-r3和r0通信

    用户部分代码: int main() { HANDLE hDevice = CreateFile(L, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ...

  9. pandas包 —— drop()、sort_values()、drop_duplicates()

    一.drop() 函数 当你要删除某一行或者某一列时,用drop函数,它不改变原有的df中的数据,而是返回另一个dataframe来存放删除后的数据. 1.命令: df.drop() 删除行:df.d ...

  10. 017、Java中使用float型

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...