POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)
传送门: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(重复次数最多的连续重复子串)的更多相关文章
- 【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串
后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的 ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- POJ 3693 Maximum repetition substring(连续重复子串)
http://poj.org/problem?id=3693 题意:给定一个字符串,求重复次数最多的连续重复子串. 思路: 这道题确实是搞了很久,首先枚举连续子串的长度L,那么子串肯定包含了r[k], ...
- poj 3693 后缀数组 重复次数最多的连续重复子串
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8669 Acc ...
- POJ 3693 Maximum repetition substring(后缀数组)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- POJ-3693-Maximum repetition substring(后缀数组-重复次数最多的连续重复子串)
题意: 给出一个串,求重复次数最多的连续重复子串 分析: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现几次. 既然长度为L的串重复出现,那么str[0],str[l],str ...
- 后缀数组 POJ 3693 Maximum repetition substring
题目链接 题意:给定一个字符串,求重复次数最多的连续重复子串. 分析:(论文上的分析)先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次.首先连续出现 1 次是肯定可以的,所以这里只考虑至少 ...
- spoj687 后缀数组重复次数最多的连续重复子串
REPEATS - Repeats no tags A string s is called an (k,l)-repeat if s is obtained by concatenating k& ...
- SPOJ - REPEATS —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/SPOJ-REPEATS REPEATS - Repeats no tags A string s is called an (k,l ...
随机推荐
- 10步写了个Django网站,正经网站···
Django做网站只要10步,真的只有10步,不信?咱们来数数-- 今天主要讲解用Pycharm编辑器搭建网站,网站功能是 实现在局域网中快速传递大文件! 比如:同事要给你个1G的文件,你丢一 ...
- 算法实验5--N皇后
实验名称 回溯法解N皇后问题 实验目的 掌握回溯递归算法.迭代算法的设计与实现: 设计回溯算法求解: 分析算法的时间复杂度. 实验环境 操作系统:win 10; 编程语言:Java: 开发工具:IDE ...
- Python使用Protobuf&&如何赋值&&如何正反序列化
前言 使用protobuf主要是两个步骤,序列化和反序列化. 关于Proto有哪些数据类型,然后如何编写,此处就不赘述了,百度一下有很多. 此文主要是总结,python使用protobuf的过程,如何 ...
- 虚拟机Linux安装Oracle容器并实现局域网其他主机访问查询
该文涉及Docker下Oracle容器的安装,主机端口的设置实现局域网内终端均能连接上Oracle数据库,图解如下: 一.关于Docker安装oracle容器可以参考下面博文: https://blo ...
- Empire
Empire 内网渗透神器 一 基本渗透 安装 git clone https://github.com/BC-SECURITY/Empire/ ./setup/install.sh 启动 ./emp ...
- ABAP 多表联合查询
inner join(等值连接) 只返回两个表中联结字段相等的行left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录right join(右联接) 返回包括右表中的所有记录 ...
- std::thread线程库详解(3)
目录 目录 前言 lock_guard scoped_lock (C++17) unique_lock shared_lock 总结 ref 前言 前两篇的博文分别介绍了标准库里面的线程和锁,这一次的 ...
- JavaScript中的深拷贝和浅拷贝!【有错误】还未修改!请逛其他园子!
JavaScript中的深拷贝和浅拷贝! 浅拷贝 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用.{也就是拷贝的是地址!简而言之就是在新的对象中修改深层次的值也会影响原来的对象!} // 2.深 ...
- history附上时间戳,history命令_Linux history命令:查看和执行历史命令
起因是这样的,一台机器客户反馈连接不上,说没有任何操作.好吧,排查吧. 1.第一步先看网络是否通: 从图中可以看到一开始是一直不通的.然后就通了,问了客户有没操作重启什么的结果说没有任何操作,还让给个 ...
- VMware vSphere (EXSI) 安装使用
VMware vSphere 镜像下载 VMware vSphere Hypervisor (ESXi) 6.7 https://my.vmware.com/cn/web/vmware/downloa ...