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 ...
随机推荐
- ORACLE RAISE
ORACLE 出错信息的输出 偷懒的办法直接在Exception 后使用raise但是错误信息不是很完整使用RAISE_APPLICATION_ERROR(-20999, DBMS_UTILITY.f ...
- ==与equals的区别
==比较两个对象在内存里是不是同一个对象,就是说在内存里的存储位置一致.两个String对象存储的值是一样的,但有可能在内存里存储在不同的地方 . ==比较的是引用而equals方法比较的是内容.pu ...
- 《基于Apache Kylin构建大数据分析平台》
Kyligence联合创始人兼CEO,Apache Kylin项目管理委员会主席(PMC Chair)韩卿 武汉市云升科技发展有限公司董事长,<智慧城市-大数据.物联网和云计算之应用>作者 ...
- php 二维数组排序
usort($info ,function($a,$b){ $a1 = $a['score']; $b1 = $b['score']; if($a1 == $b1) return 0; return ...
- 289. Game of Life -- In-place计算游戏的下一个状态
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...
- ShellExecute调用另外一个进程(demo为一个控制led的一段代码)
public enum ShowCommands : int { SW_HIDE = 0, SW_SHOWNORMAL = 1, ...
- 深入浅出Mybatis系列(九)---强大的动态SQL
上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis ...
- 超级文件搜索器(SuperSearch)
写了个工具,各个分享渠道上传太难了,在这里分享给大家吧! 中文名称:超级文件搜索器 英文名称: SuperSearch 适用对象:硬盘里文件达到数万至数千万级的用户 运行环境:WindowXP,Wi ...
- java selenium (十) 操作浏览器
本篇文章介绍selenium 操作浏览器 阅读目录 浏览器最大化 前进,后退, 刷新 public static void testBrowser(WebDriver driver) throws E ...
- C#中的@符号用法
C#中的@符号其实有很多的用法,我们来看看@有什么神奇之处. 1.限定字符串 用 @ 符号加在字符串前面表示其中的转义字符“不”被处理. 如果我们写一个文件的路径,例如"D:/文本文件&qu ...