题目

The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

大意是,给你一个字符串,让你输出其中重复次数最多的重复连续字串,如果次数相同就输出字典序最小的。

思路

一开始不好想。

首先,枚举串的长度\(L\),然后枚举区间\([1,L]\),\([L+1,2*L]\),会发现,一个连续重复子串总会被截头去尾的被枚举到。

比如cabababc,在枚举到长度\(L=2\)的时候,中间的那段baba就会被枚举到,然而实际上可能是去了头尾的,注意到LCP求出后后面会多出一段,定义\(R=LCP\),那么,R%L就是多出来的一段,可以看成是前面少取了L-R%L这一段,然后判断是不是可以把这一段补上,就完成了第一步:找到一段区间内的最长重复连续子串。

然后考虑第二步:要求字典序最小。

我们把这些可能成为答案的串先存起来,然后按照的顺序一遍扫描,因为sa天然有序,所以就可以得到最终的答案了。

代码

#include<cstdio>
#include<string.h>
#include<algorithm>
#include<iostream>
#define M 100005
using namespace std;
int sa[M],rk[M],t1[M],t2[M],tmp[M],cnt1[M],cnt2[M],H[M];
struct node{int x,id;bool operator < (const node&  res)const{if(x!=res.x)return x<res.x;return id<res.id;}
}A[M];
void Init(char *s,int n){for(int i=1;i<=n;i++)A[i]=(node){s[i],i};sort(A+1,A+n+1);for(int i=1;i<=n;i++)sa[i]=A[i].id; rk[sa[1]]=1;for(int i=2;i<=n;i++){rk[sa[i]]=rk[sa[i-1]];if(s[sa[i]]!=s[sa[i-1]])rk[sa[i]]++; }for(int l=1;rk[sa[n]]<n;l<<=1){for(int i=0;i<=n;i++)cnt1[i]=cnt2[i]=0;for(int i=1;i<=n;i++)cnt1[t1[i]=rk[i]]++,cnt2[t2[i]=(l+i<=n)?rk[i+l]:0]++;for(int i=1;i<=n;i++)cnt1[i]+=cnt1[i-1],cnt2[i]+=cnt2[i-1];for(int i=n;i>=1;i--)tmp[cnt2[t2[i]]--]=i;for(int i=n;i>=1;i--)sa[cnt1[t1[tmp[i]]]--]=tmp[i];rk[sa[1]]=1;for(int i=2;i<=n;i++){rk[sa[i]]=rk[sa[i-1]];if(t1[sa[i]]!=t1[sa[i-1]]||t2[sa[i]]!=t2[sa[i-1]])rk[sa[i]]++;}}for(int i=1,j=0;i<=n;i++){j-=j>0;while(s[i+j]==s[sa[rk[i]-1]+j])j++;H[rk[i]]=j;}
}
struct Stable{int mn[M][21],Log[M];void Init(int n){for(int i=1;i<=n;i++){mn[i][0]=H[i];if(i>1)Log[i]=Log[i>>1]+1;}for(int j=1;j<21;j++)for(int i=1;i+(1<<j-1)<=n;i++)mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]);}int Query(int l,int r){int t=Log[r-l+1];return min(mn[l][t],mn[r-(1<<t)+1][t]);}
}st;
int LCP(int l,int r){l=rk[l],r=rk[r];if(l>r)swap(l,r);return st.Query(l+1,r);
}
char S[M];
int n,cas=0,a[M],cnt;
int main(){while(scanf("%s",S+1)&&S[1]!='#'){n=strlen(S+1);Init(S,n);st.Init(n);int ans=0;for(int L=1;L<=n;L++){for(int i=1;i<=n;i+=L){int R=LCP(i,i+L),step=R/L+1,k=i-(L-R%L);if(k>=0&&R%L)if(LCP(k,k+L)>=R)step++;if(step>ans){ans=step;cnt=0;a[cnt++]=L;}else if(step==ans)a[cnt++]=L;}}int len=-1,st;for(int i=1;i<=n&&len==-1;i++){for(int j=0;j<cnt;j++){int L=a[j];if(LCP(sa[i],sa[i]+L)>=(ans-1)*L){len=L;st=sa[i];break;}}}       printf("Case %d: ",++cas);for(int i=st;i<st+len*ans;i++)printf("%c",S[i]);putchar('\n');for(int i=1;i<=n;i++)S[i]=0;}return 0;
}

转载于:https://www.cnblogs.com/zryabc/p/11202144.html

POJ3693 Maximum repetition substring相关推荐

  1. POJ-3693 Maximum repetition substring 后缀数组

    题目链接:http://poj.org/problem?id=3693 求字符串的重复次数最多的且字典序最小的字串. 很不错的题目.罗穗骞大牛论文的模板题,摘了Neo / Add ~0U>> ...

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

    题目链接:点击查看 题目大意:给出一个字符串,求出字符串中 重复次数最多的连续重复子串 ,如果有多个答案,输出字典序最小的 题目分析:又是一个模板题,这里放一个大佬的博客,讲的很清楚: https:/ ...

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

    题目大意: 求出字典序最小,重复次数最多,的子串. 思路分析: RMQ + height 数组可以求出任意两个后缀的lcp 我们枚举答案字符串的重复的长度. 如果这个字符串的长度为 l ,而且这个字符 ...

  4. Leetcode-1156 Swap For Maximum Repeated Substring(单字符重复子串的最大长度)

    因为只能交换一次,先考虑如果不交换最大的值. 接下来考虑交换,有四种情况 ① aaabaaa型 交换一下可以将相邻的两块连在一起,答案就是两块长度之和 ② aaabbbaaaa 交换一下也不能连起两块 ...

  5. 重走长征路---OI每周刷题记录---1月17日 2015

    总目录详见https://blog.csdn.net/mrcrack/article/details/84471041 做题原则,找不到测评地址的题不做.2018-11-28 重走长征路---OI每周 ...

  6. kuangbin带你飞专题合集

    题目列表 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题二 搜索进阶 [kuangbin带你飞]专题三 Dancing Links [kuangbin带你飞]专题四 最短路 ...

  7. 算法学习经典例题整理

    陆续会对本篇博客进行更新! 搜索:https://vjudge.net/contest/292597 区间DP:https://vjudge.net/contest/293892 树状背包:https ...

  8. poj 3693 后缀数组

    链接:点我 1 /* 2 * POJ 3693 Maximum repetition substring 3 * 先穷举长度L,然后求长度为L的子串最多能连续出现多少次 4 * 既然长度为L的串重复出 ...

  9. 投资组合风险收益率公式_投资组合分析的基础收益和亏损

    投资组合风险收益率公式 In this story, we are going to do some basic portfolio returns analysis in python. 在这个故事 ...

最新文章

  1. 软件测试的准入准出是什么?标准是什么?
  2. htc在ubuntu上找不到devieces,提示权限不够的解决方法
  3. 现代c++之线程本地存储thread_local
  4. c语言中的运算符按位或,|按位或运算符
  5. redis setnx 分布式锁_Redis 分布式锁PHP
  6. matlab错误使用builtin,MATLAB环境下运行MATLAB函数时发生异常
  7. 剑指offer面试题68 - I. 二叉搜索树的最近公共祖先(递归)(二叉搜索树)
  8. reactor ---- 反应堆模型
  9. shell编程——判断条件
  10. chrome developer tool 调试技巧2
  11. laravel 集合从父中移除_在 Laravel 7 中优雅使用 UUID 教程
  12. 安装rational rose软件教程
  13. 基于MATLAB的无线视频传输
  14. python如何运行js代码
  15. 把mysql数据展示为图表_怎么从数据库中调出数据并生成动态图表?
  16. 设置模式之UML中的类图及类图之间的关系
  17. 东芝 rc100 linux,东芝RC100 M.2 NVMe固态硬盘HMB特性解读
  18. 我们工作到底为了什么
  19. 怎么找网页源文件位置_win7系统查看网页源文件的三种方法
  20. tzoj 3847 Mowing the Lawn (单调队列 )

热门文章

  1. windows 下FFMPEG的编译方法 附2012-9-19发布的FFMPEG编译好的SDK下载
  2. SecureCRT快捷键
  3. Apple Swift编程语言入门教程
  4. nagios监控windows USBKEY
  5. 数据库的几种联结,union,union all ,inner jion ,left jion,right jion ,cross jion
  6. VS2005调试ASP.NET出现未能开始侦听端口解决办法
  7. 加强linux操作系统DNS服务安全
  8. salt-ssh 安装salt-minion 笔记
  9. pt-table-checksum 原理解析
  10. [禅悟人生]越忙的人时间越多