poj3693
//Accepted 12004 KB 407 ms
/*
source:poj3693
time :20150819
by :songt
*/
/*题解:
搞了一天,总算弄完了
首先,我们来明确一个问题 1.如果一个字符串S由一个子串S1长度为L重复K次得到,那么lcp(0,l)=(K-1)*L;
而如果一个字符串中存在lcp(i,i+L)=m,那么字符串中就存在重复m/L+1次的子串
这个可以画个图看下
下面我们按照论文里的思路,枚举每个循环节的长度L,假设某个长度为L的子串在原字符中出现了两次以上,那么由
容斥原理可知,这段连续重复的子串S一定包括了s[0],s[L],s[2*L],s[3*L],...中的连续的两个,这样我们可以枚举找到
包括最开始的两个是哪两个,假设是s[i*L]和s[(i+1)*L],那么求lcp(i*L,(i+1)*L)=m,由1可知,原字符串中从i*L到(i+1)*L这段
长度为L的子串,一定重复了m/L+1,但是由于i*L和(i+1)*L不一定是重复子串的第一个开始位置,即i*L不一定对应S[0],所以我们
尝试调整开始的位置,假设i*L对应于S(0,L)中的某个字符,那么lcp(i*L,(i+1)*L)=m中的m就会比(m/L)*m大一点,这一点就是因为i*L
不对应S[0],而对应了S(0,L)中的某个字符造成的,这样我们就可以知道,多匹配的这一点长度就对应(i*L对应于S[k] 0<k<L) k到L这一段
长度,所以应该尝试把i*L向前移动L-m%L个字符(m%L!=0).这样我们就可以求出最大的重复次数。
加入最多只重复了1次也就是没有重复,那么用上面的方法也可以求得。
接下来是求最小字典序的步骤,我们在求最大重复次数的时候,保存对应可能的长度L,那么我们可以从sa[1]到sa[n]枚举,
如果sa[i]和某个长度L能够满足重复次数的要求,那么就得到了答案,枚举中遇到的第一个就是结果,应为sa[1]到sa[n]已经
按照字典序排序
*/
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
;
int wa[imax_n],wb[imax_n],wn[imax_n],wv[imax_n];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)
{
int i,j,k,p,*x=wa,*y=wb,*t;
;i<m;i++) wn[i]=;
;i<n;i++) wn[x[i]=r[i]]++;
;i<m;i++) wn[i]+=wn[i-];
;i>=;i--) sa[--wn[x[i]]]=i;
,p=;p<n;j*=,m=p)
{
,i=n-j;i<n;i++) y[p++]=i;
;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
;i<n;i++) wv[i]=x[y[i]];
;i<m;i++) wn[i]=;
;i<n;i++) wn[wv[i]]++;
;i<m;i++) wn[i]+=wn[i-];
;i>=;i--) sa[--wn[wv[i]]]=y[i];
,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return ;
}
int rank[imax_n];
int height[imax_n];
int a[imax_n];
char s[imax_n];
int sa[imax_n];
int n;
void calHeight(int *r,int *sa,int n)
{
;
;i<=n;i++) rank[sa[i]]=i;
;i<n;height[rank[i++]]=k)
,j=sa[rank[i]-];r[i+k]==r[j+k];k++);
return ;
}
int min(int a,int b)
{
return a<b?a:b;
}
];
int mm[imax_n];
void initRMQ(int n,int b[])
{
mm[]=-;
;i<=n;i++)
{
mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
dp[i][]=b[i];
}
;j<=mm[n];j++)
{
;i+(<<j)-<=n;i++)
{
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
}
}
}
int rmq(int x,int y)
{
x=rank[x];
y=rank[y];
if (x>y)
{
int tmp=x;
x=y;
y=tmp;
}
x++;
];
<<k)+][k]);
}
vector<int > vec;
void Deal()
{
n=strlen(s);
;i<n;i++)
{
a[i]=(int )s[i];
}
a[n]=;
da(a,sa,n+,);
calHeight(a,sa,n);
initRMQ(n,height);
vec.clear();
;
;l<=n/;l++) //枚举循环节的长度
{
;i+l<n;i+=l) //找对应子串S第一个循环节和第二个循环节的位置
{
int length=rmq(i,i+l); //求出重复的次数
;
int newpos=i-(l-length%l);
&& length%l && rmq(newpos,newpos+l)>length) times++; //尝试更新结果
if (times>max_times)
{
vec.clear();
vec.push_back(l);
max_times=times;
}
else if (times==max_times)
{
vec.push_back(l);
}
}
}
sort(vec.begin(),vec.end());
int cnt=unique(vec.begin(),vec.end())-vec.begin();
//printf("max_times=%d\n",max_times);
//for (int i=0;i<cnt;i++)
//{
// printf("length=%d\n",vec[i]);
//}
int start,length;
//printf("size=%d\n",vec.size());
;
;i<=n && !flag;i++)
{
;j<cnt && !flag;j++)
{
)*vec[j])
{
start=sa[i];
length=vec[j]*max_times;
flag=;
}
}
}
//printf("start=%d length=%d\n",start,length);
for (int i=start;i<start+length;i++)
printf("%c",s[i]);
printf("\n");
}
int main()
{
int T;
;
)
{
) break;
printf("Case %d: ",++t);
Deal();
}
;
}
poj3693的更多相关文章
- 【poj3693】Maximum repetition substring(后缀数组+RMQ)
题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...
- 【poj3693】 Maximum repetition substring
http://poj.org/problem?id=3693 (题目链接) 题意 给定一个字符串,求重复次数最多的连续重复子串,若存在多组解,输出字典序最小的. Solution 后缀数组论文题,就是 ...
- poj3693(后缀数组)
poj3693 题意 给出一个串,求重复次数最多的连续重复子串,输出字典序最小的. 分析 论文 例8(P21). Sparse-Table算法预处理出任意两个后缀串的LCP. code #includ ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- 【SPOJ687&POJ3693】Maximum repetition substring(后缀数组)
题意: n<=1e5 思路: From http://hzwer.com/6152.html 往后匹配多远 r 用ST表求lcp即可...往前 l 就把串反过来再做一下.. 但是有可能求出来的最 ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- poj3693 Maximum repetition substring
题意 给出一个长度为\(n(n\leqslant 100000)\)的串,求一个字典序最小的子串使得它是某个字符串重复\(k\)次得到的,且\(k\)最大 题解 后缀数组论文上的题,跟上一篇uva那个 ...
- poj3693之后缀数组
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5946 Accepted: 1799 Description The r ...
- Maximum repetition substring (poj3693 后缀数组求重复次数最多的连续重复子串)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6328 Acc ...
随机推荐
- spring框架学习(六)AOP
AOP(Aspect-OrientedProgramming)面向方面编程,与OOP完全不同,使用AOP编程系统被分为方面或关注点,而不是OOP中的对象. AOP的引入 在OOP面向对象的使用中,无可 ...
- 根据大小生成对应尺寸网络图片的网址(mark)
当开发程序时,需要用到一些临时图片替代时,需要快速生成的话,以下的几个网址可提供帮助.mark一下,方便以后使用. http://lorempixel.com/http://placehold.it/ ...
- cocos2d-x 图片性能测试
本文是原创文章,如需转载,请注明文章出处 本次测试使用的cocos2d-x版本是3.9,测试环境是XCode7自带的iphone5 一.JPG格式与PVR.CCZ格式对比 1.占用空间对比 a)不透明 ...
- Gradle 使用本地的Jar包(gradle oracle ojdbc14 )
Gradle 使用本地的Jar包(gradle oracle ojdbc14 ) 因为Oracle的驱动包在Maven上是没办法直接下载到的,所以在使用Gradle的使用,会导致无法加载Oracle, ...
- (47) odoo详细操作手册
odoo 8 详细操作手册, ERP(Odoo8.0)操作手册-v1.10(陈伟明).pdf 链接: http://pan.baidu.com/s/1hsp0bVQ 密码: r9tt 花了将近9个月时 ...
- mysql通用包安装
mysql 版本: mysql-5.7.16-linux-glibc2.5-x86_64.tar.gz 解压后的初始化: mysqld --defaults-file=/etc/my.cnf --us ...
- WPF知识总结(一)
在一个项目中, 发现有的项目引用的动态库是一个网页地址,下面就看看这个网页地址怎么来的. 目标:新建一个WPF工程,实现一个用户控件的功能.在 工程中加入一个类库,然后在类库中增加一个用户控件页面,在 ...
- [原创]在Linux系统Ubuntu14.04上安装部署docker。
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...
- winform学习笔记02
Hashtable 数据遍历的几种方式 ---Hashtable 在集合中称为键值对,它的每一个元素的类型是 DictionaryEntry,由于Hashtable对象的键和值都是Object类型,决 ...
- 【图像处理】【SEED-VPM】2.接口
—————————————————————————————————————————————————————————————— 对比 ①最好是HDMI: ②分量也是高清的范围,得是比点对点的HDMI低一 ...