传送门:POJ - 3693  

题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串。

题解:

比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现几次。既然长度为L的串重复出现,那么str[0],str[l],str[2*l]……中肯定有两个连续的出现在字符串中。

那么就枚举连续的两个,然后从这两个字符前后匹配,看最多能匹配多远。即以str[i*l],str[i*l+l]前后匹配,这里是通过查询suffix(i*l),suffix(i*l+l)的最长公共前缀。通过rank值能找到i*l,与i*l+l的排名,我们要查询的是这段区间的height的最小值,通过RMQ预处理达到查询为0(1)的复杂度

设LCP长度为M, 则答案显然为M / L + 1, 但这不一定是最好的, 因为答案的首尾不一定再我们枚举的位置上. 我的解决方法是, 我们考虑M % L的值的意义, 我们可以认为是后面多了M % L个字符, 但是我们更可以想成前面少了(L - M % L)个字符! 所以我们求后缀j * L - (L - M % L)与后缀(j+ 1) * L - (L - M % L)的最长公共前缀。即把之前的区间前缀L-M%L即可。

然后把可能取到最大值的长度L保存,由于 题目要求字典序最小,通过sa数组进行枚举,取到的第一组,肯定是字典序最小的。

题解的出处:https://blog.csdn.net/acm_cxlove/article/details/7941205

  1 #include<cstdio>
2 #include<algorithm>
3 #include<queue>
4 #include<iostream>
5 #include<cmath>
6 #include<cstring>
7 using namespace std;
8
9 const int maxn = 1e5+10;
10 int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
11 int rnk[maxn],height[maxn];
12 char s[maxn];
13 int r[maxn];
14
15 //sa:字典序中排第i位的起始位置在str中第sa[i] sa[1~n]为有效值
16
17 //rnk:就是str第i个位置的后缀是在字典序排第几 rnk[0~n-1]为有效值
18
19 //height:字典序排i和i-1的后缀的最长公共前缀 height[2~n]为有效值,第二个到最后一个
20
21 int cmp(int *r,int a,int b,int k)
22 {
23 return r[a]==r[b]&&r[a+k]==r[b+k];
24 }
25
26 void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
27 {
28 int i,j,p,*x=wa,*y=wb,*t;
29 for(i=0; i<m; i++) wsf[i]=0;
30 for(i=0; i<=n; i++) wsf[x[i]=r[i]]++;
31 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
32 for(i=n; i>=0; i--) sa[--wsf[x[i]]]=i;
33 p=1;
34 j=1;
35 for(; p<=n; j*=2,m=p){
36 for(p=0,i=n+1-j; i<=n; i++) y[p++]=i;
37 for(i=0; i<=n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
38 for(i=0; i<=n; i++) wv[i]=x[y[i]];
39 for(i=0; i<m; i++) wsf[i]=0;
40 for(i=0; i<=n; i++) wsf[wv[i]]++;
41 for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
42 for(i=n; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
43 swap(x,y);
44 x[sa[0]]=0;
45 for(p=1,i=1; i<=n; i++)
46 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
47 }
48 }
49
50 void getheight(int *r,int n)//n为添加0后的总长
51 {
52 int i,j,k=0;
53 for(i=1; i<=n; i++) rnk[sa[i]]=i;
54 for(i=0; i<n; i++){
55 if(k)
56 k--;
57 else
58 k=0;
59 j=sa[rnk[i]-1];
60 while(r[i+k]==r[j+k])
61 k++;
62 height[rnk[i]]=k;
63 }
64 }
65
66 int dp[maxn][40];
67
68 void rmq_init(int n){
69
70 int m=floor(log(n+0.0)/log(2.0));
71 for(int i=1;i<=n;i++)dp[i][0]=height[i];
72 for(int j=1;j<=m;j++){
73 for(int i=n;i;i--){
74 dp[i][j]=dp[i][j-1];
75 if(i+(1<<(j-1))<=n){
76 dp[i][j]=min(dp[i][j],dp[i+(1<<(j-1))][j-1]);
77 }
78 }
79 }
80 }
81
82 int rmq(int l,int r){
83
84 int a=rnk[l],b=rnk[r];
85 if(a>b)swap(a,b);
86 a++;
87 int k=floor(log(b-a+1.0)/log(2.0));
88 return min(dp[a][k],dp[b-(1<<k)+1][k]);
89 }
90
91 int main()
92 {
93 ios::sync_with_stdio(false);
94 cin.tie(0);
95 cout.tie(0);
96 int t=1;
97 while(cin>>s){
98 if(s[0]=='#') break;
99 int len=strlen(s);
100 for(int i=0;i<len;i++) r[i]=s[i]-'a'+1;
101 r[len]=0;
102 getsa(r,sa,len,150);
103 getheight(r,len);
104 rmq_init(len);
105 int ans=0;
106 int pos=0,p=0;
107 for(int k=1;k<len;k++){ //枚举长度
108 for(int i=0;i+k<len;i+=k){ //第i段
109 int n=rmq(i,i+k); //每一段的公共前缀最小值
110 n--;
111 for(int j=0;j<=k-1;j++){ //枚举每一段的起点
112 int now=i-j;
113 if((now<0||s[now]!=s[now+k])&&j) break;
114 n++;
115 int sum=n/k+1;
116 if(sum>ans||(sum==ans&&rnk[now]<rnk[pos])){
117 ans=sum;
118 pos=now;
119 p=k;
120 }
121 }
122 }
123 }
124 cout<<"Case "<<t++<<": ";
125 if(ans<=1){
126 char tmp='z';
127 for(int i=0;i<len;i++) tmp=min(tmp,s[i]);
128 cout<<tmp<<endl;
129 }
130 else{
131 for(int i=0;i<ans*p;i++){
132 cout<<s[i+pos];
133 }
134 cout<<endl;
135 }
136 }
137 return 0;
138 }

POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)的更多相关文章

  1. 【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串

    后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的 ...

  2. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

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

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

  4. poj 3693 后缀数组 重复次数最多的连续重复子串

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8669   Acc ...

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

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

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

    题意: 给出一个串,求重复次数最多的连续重复子串 分析: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现几次. 既然长度为L的串重复出现,那么str[0],str[l],str ...

  7. 后缀数组 POJ 3693 Maximum repetition substring

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

  8. spoj687 后缀数组重复次数最多的连续重复子串

    REPEATS - Repeats no tags  A string s is called an (k,l)-repeat if s is obtained by concatenating k& ...

  9. SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags  A string s is called an (k,l ...

随机推荐

  1. 科来网络通讯协议图2019版(OSI七层模型)

    来源:http://www.colasoft.com.cn/download/protocols_map.php 自己把它转成了图片,好做查看:https://www.lanzous.com/ib5h ...

  2. 天梯赛练习 L3-006 迎风一刀斩 (30分) 几何关系

    题目分析: 对于给出的两个多边形是否可以组成一个矩形,这里我们分以下几种情况讨论 1.首先对于给出的两个多边形只有3-3,3-4,3-5,4-4才有可能组成一个矩形,并且两个多边形只可能是旋转90,1 ...

  3. 十四:SQL注入之类型及提交注入

    简要明确参数类型 数字,字符,搜索,json等 简要明确请求方法 GET,POST,COOKIE,REQUEST,HTTP头 其中SQL语句干扰符号:' " % ) } 等,具体查看用法 非 ...

  4. 浅谈Go中的time.After

    go的一条哲学是 不要通过共享来实现通信,而是通信来实现共享 多协程之间通过 channel 来实现通信,而普遍会遇到的问题是,如何进行超时控制,资料一查询,需要配置select和time.After ...

  5. 【Linux】Linux下如何分区及如何格式化

    环境:CentOS7.1 磁盘大小是1.8T 将磁盘/dev/sda分一个分区,分区类型为xfs fdisk /dev/sda n    --创建新分区 p  --创建分区类型为主分区 1  --主分 ...

  6. JVM 判断对象已死,实践验证GC回收

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 提升自身价值有多重要? 经过了风风雨雨,看过了男男女女.时间经过的岁月就没有永恒不变 ...

  7. 04--Docker数据卷和数据卷容器

    .为什么要使用数据卷: Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了.为了能保存数据在docke ...

  8. Python执行程序实可视化_heartrate

    最近发现了一个Python程序执行的简单实时可视化神器,名字叫 heartrate,安装完运行可以看到下面这样的炫酷过程. 虽然很炫酷,但有点看不懂. 来解释下,左边的动态数字代表每行被触发的次数.变 ...

  9. uni-app开发经验分享五: 解决三端页面兼容问题的方法

    在做uni-app开发的过程中,我们最头疼可能不是开发的过程中的逻辑,而是最后要做的三端兼容测试和修改,在我开发的项目中,这一步都是最头疼和令人头秃的过程,这里总结一些个人开发遇到的问题,希望对大家有 ...

  10. Mac 禁用动画

    # opening and closing windows and popovers defaults write -g NSAutomaticWindowAnimationsEnabled -boo ...