POJ3693 Maximum repetition substring 后缀数组
时间:2019-10-24
本文章向大家介绍POJ3693 Maximum repetition substring 后缀数组,主要包括POJ3693 Maximum repetition substring 后缀数组使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
POJ - 3693 Maximum repetition substring
题意
输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的
Sample input
ccabababc
daabbccaa
#
Sample Output
Case 1: ababab
Case 2: aa
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5+5; 7 char s[maxn]; 8 int sa[maxn], t[maxn], t2[maxn], c[maxn]; 9 int n; 10 //构造字符串s的后缀数组, 每个字符值必须为0 ~ m-1 11 void build_sa(int m) { 12 int *x = t, *y = t2; 13 //基数排序 14 for(int i = 0; i < m; i++) c[i] = 0; 15 for(int i = 0; i < n; i++) c[x[i] = s[i]]++; 16 for(int i = 1; i < m; i++) c[i] += c[i-1]; 17 for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; 18 for(int k = 1; k <= n; k <<= 1) { 19 int p = 0; 20 //直接利用sa数组排序第二关键字 21 for(int i = n-k; i < n; i++) y[p++] = i; 22 for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 23 //基数排序第一关键字 24 for(int i = 0; i < m; i++) c[i] = 0; 25 for(int i = 0; i < n; i++) c[x[y[i]]]++; 26 for(int i = 1; i < m; i++) c[i] += c[i-1]; 27 for(int i = n-1; i>= 0; i--) sa[--c[x[y[i]]]] = y[i]; 28 //根据sa和y数组计算新的x数组 29 swap(x, y); 30 p = 1; 31 x[sa[0]] = 0; 32 for(int i = 1; i < n; i++) 33 x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++); 34 if(p >= n) break; 35 m = p; 36 } 37 } 38 39 int rank_[maxn]; //rank[i]代表后缀i在sa数组中的下标 40 int height[maxn]; //height[i] 定义为sa[i-1] 和 sa[i] 的最长公共前缀 41 //后缀j和k的LCP长度等于RMQ(height, rank[j]+1, rank[k]) 42 void get_height() { 43 int i, j, k = 0; 44 for(int i = 0; i < n; i++) rank_[sa[i]] = i; 45 for(int i = 0; i < n; i++) { 46 if(!rank_[i]) continue; 47 int j = sa[rank_[i]-1]; 48 if(k) k--; 49 50 while(s[i+k] == s[j+k]) k++; 51 height[rank_[i]] = k; 52 } 53 } 54 int d[maxn][50]; 55 void rmq_init() { 56 for(int i = 0; i < n; i++) d[i][0] = height[i]; 57 for(int j = 1; (1<<j) <= n; j++) 58 for(int i = 0; i + (1<<j) - 1 < n; i++) 59 d[i][j] = min(d[i][j-1], d[i+(1<<(j-1))][j-1]); 60 } 61 int rmq(int l, int r) { 62 if(l == r) return n-l; 63 if(rank_[l] > rank_[r]) swap(l, r); 64 int L = rank_[l]+1; 65 int R = rank_[r]; 66 int k = 0; 67 while((1<<(k+1)) <= R-L+1) k++; 68 return min(d[L][k], d[R-(1<<k)+1][k]); 69 } 70 71 int a[maxn]; 72 int main() { 73 int kase = 0; 74 while(~scanf("%s", s) && s[0] != '#') { 75 int L = strlen(s); 76 n = L + 1; 77 build_sa(128); 78 get_height(); 79 rmq_init(); 80 int mx = 0; 81 int cnt = 0; 82 // 寻找重复次数最多的连续子串单个子串的长度,可能有多种重复次数相同的子串 83 for(int l = 1; l <= L; l++) { 84 for(int j = 0; j + l < L; j += l) { 85 int k = rmq(j, j + l); // lcp 86 int res = k / l + 1; 87 int pos = j - (l - (k % l)); 88 if(pos >= 0 && k % l && rmq(pos, pos + l)) res++; 89 if(res > mx) { 90 mx = res; 91 cnt = 0; 92 a[cnt++] = l; 93 } else if(res == mx) { 94 a[cnt++] = l; 95 } 96 } 97 } 98 // 找字典序最小 99 int len = 0, st; 100 for(int i = 1; i < n && !len; i++) { 101 for(int j = 0; j < cnt; j++) { 102 if(rmq(sa[i], sa[i] + a[j]) >= (mx - 1) * a[j]) { 103 len = a[j]; 104 st = sa[i]; 105 break; 106 } 107 } 108 } 109 printf("Case %d: ", ++kase); 110 for(int i = st; i < st + len * mx; i++) { 111 printf("%c", s[i]); 112 } 113 printf("\n"); 114 } 115 return 0; 116 }
原文地址:https://www.cnblogs.com/wstong/p/11731712.html
- Flash/Flex学习笔记(13):对象拖动(startDrag/stopDrag)
- 原来Silverlight 4中是可以玩UDP的!
- Flash/Flex学习笔记(12):FMS 3.5之如何做视频实时直播
- Flash/Flex学习笔记(11):如何检测摄像头是否被占用
- Flash/Flex学习笔记(10):FMS 3.5之Hello World!
- Swarm基于多主机容器网络-overlay networks 梳理
- 未来AI可能会淘汰180万个工作岗位,你感到恐惧了吗
- css基础:把所有背景图都集成在一张图片上,减少图片服务器请求次数
- Docker可视化界面(Consul+Shipyard+Swarm+Service Discover)部署记录
- windows 2008上启用防火墙后sqlserver 2005经常出现连接超时的解决办法
- 重温delphi之控制台程序:Hello World!
- Docker集中化web界面管理平台-Shipyard部署记录
- "Goole项目托管"及"CodePlex发布开源项目"要点
- Docker网络解决方案-Calico部署记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- dotnet OpenXML 解析 PPT 文本字体获取详解
- R练习50题 - 第一期
- [889]python处理HTML转义字符
- python 利用jinja2模板生成html代码实例
- vue项目使用 富文本 封装
- typescript基础篇(5):类
- .Net微服务实战之Kubernetes的搭建与使用
- 使用Prometheus监控Golang服务-基于YoyoGo框架
- 使用jedis面临的非线程安全问题
- 基于UVM的UART验证环境
- 潘石屹用Python解决100个问题 | 打印菱形
- Android:源码解析 Dialog的窗口机制
- Java|获取图片rgb值
- (数据科学学习手札93)利用geopandas与PostGIS进行交互
- 设计模式(三):旅行的角度理解抽象工厂模式