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 ...
随机推荐
- nginx文件结构与解析,例子
1.nginx文件结构 1 ... #全局块 2 3 events { #events块 4 ... 5 } 6 7 http #http块 8 { 9 ... #http全局块 10 server ...
- zabbix自定义监控nginx
nginx配置ngx_status 1.编译安装时带上--with-http_stub_status_module参数 2.vi nginx.conf location ~* ^/ngx_status ...
- IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerp
[root@k8s-master ~]# scp /etc/sysctl.d/k8s.conf root@192.168.30.23:/etc/sysctl.d/k8s.conf@@@@@@@@@@@ ...
- 代码页(CodePage)列表
代码页编号 国家地区或语言37 IBM037 IBM EBCDIC (US-Canada) 437 IBM437 ...
- centos7下 开启/关闭/查看firewall运行状态命令
1.开启防火墙:systemctl start firewalld.service [root@localhost bin]# systemctl start firewalld.service [r ...
- PAT练习num2-挖掘机技术哪家强
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 1 的正整数 N,即参赛人数.随后 N 行, ...
- Java中的深浅拷贝问题,你清楚吗?
一.前言 拷贝这个词想必大家都很熟悉,在工作中经常需要拷贝一份文件作为副本.拷贝的好处也很明显,相较于新建来说,可以节省很大的工作量.在Java中,同样存在拷贝这个概念,拷贝的意义也是可以节省创建对象 ...
- mysql 设置外键约束时如何删除数据
Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构 解决方法是在Mysql中取消外键约束: SET FOREIGN_KEY_CHECKS=0; 然后将原来表的数据导出到sql语句,重新 ...
- go语言rpc学习
rpc 就是 远程过程调用 指的是调用远端服务器上的程序的方法整个过程. rpc 理论 RPC技术在架构设计上有四部分组成,分别是:客户端.客户端存根.服务端.服务端存根. 客户端:服务调用发 ...
- windows10 中 svn 代码统计工具 StatSVN 使用详解
1.下载TortoiseSVN 下载地址 ps:安装时务必选上命令行的svn命令. 2.下载StatSVN 官网地址 官网上目前时0.7.0版本,我的svn是1.12.0版本,运行时会报错: 所以建议 ...