POJ 3693 Maximum repetition substring (后缀数组+RMQ)
题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的。
析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2].....这些点中相邻的两个,然后向前和向后匹配,
看看最大的匹配多大,然后把所有的答案记录下来,最后再从sa中开始枚举答案,第一个就是字典序最小的。
代码如下:
- #pragma comment(linker, "/STACK:1024000000,1024000000")
- #include <cstdio>
- #include <string>
- #include <cstdlib>
- #include <cmath>
- #include <iostream>
- #include <cstring>
- #include <set>
- #include <queue>
- #include <algorithm>
- #include <vector>
- #include <map>
- #include <cctype>
- #include <cmath>
- #include <stack>
- #include <sstream>
- #define debug() puts("++++");
- #define gcd(a, b) __gcd(a, b)
- #define lson l,m,rt<<1
- #define rson m+1,r,rt<<1|1
- #define freopenr freopen("in.txt", "r", stdin)
- #define freopenw freopen("out.txt", "w", stdout)
- using namespace std;
- typedef long long LL;
- typedef unsigned long long ULL;
- typedef pair<int, int> P;
- const int INF = 0x3f3f3f3f;
- const LL LNF = 1e16;
- const double inf = 0x3f3f3f3f3f3f;
- const double PI = acos(-1.0);
- const double eps = 1e-8;
- const int maxn = 1e5 + 10;
- const int mod = 1e9 + 7;
- const int dr[] = {-1, 0, 1, 0};
- const int dc[] = {0, 1, 0, -1};
- const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
- int n, m;
- const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- inline bool is_in(int r, int c){
- return r >= 0 && r < n && c >= 0 && c < m;
- }
- struct Array{
- int sa[maxn], s[maxn], t[maxn], t2[maxn];
- int r[maxn], h[maxn], c[maxn], dp[maxn][20];
- int n;
- void init(){
- n = 0; memset(sa, 0, sizeof sa);
- }
- void build_sa(int m){
- int *x = t, *y = t2;
- for(int i = 0; i < m; ++i) c[i] = 0;
- for(int i = 0; i < n; ++i) ++c[x[i] = s[i]];
- for(int i = 1; i < m; ++i) c[i] += c[i-1];
- for(int i = n-1; i >= 0; --i) sa[--c[x[i]]] = i;
- for(int k = 1; k <= n; k <<= 1){
- int p = 0;
- for(int i = n-k; i < n; ++i) y[p++] = i;
- for(int i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k;
- for(int i = 0; i < m; ++i) c[i] = 0;
- for(int i = 0; i < n; ++i) ++c[x[y[i]]];
- for(int i = 1; i < m; ++i) c[i] += c[i-1];
- for(int i = n-1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i];
- swap(x, y);
- p = 1; x[sa[0]] = 0;
- for(int i = 1; i < n; ++i)
- x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
- if(p >= n) break;
- m = p;
- }
- }
- void getHight(){
- int k = 0;
- for(int i = 0; i < n; ++i) r[sa[i]] = i;
- for(int i = 0; i < n; ++i){
- if(k) --k;
- int j = sa[r[i]-1];
- while(s[i+k] == s[j+k]) ++k;
- h[r[i]] = k;
- }
- }
- void rmq_init(){
- for(int i = 1; i <= n; ++i) dp[i][0] = h[i];
- for(int j = 1; (1<<j) <= n; ++j)
- for(int i = 1; i + (1<<j) <= n; ++i)
- dp[i][j] = min(dp[i][j-1], dp[i+(1<<j-1)][j-1]);
- }
- int query(int L, int R){
- L = r[L]; R = r[R];
- if(L > R) swap(L, R);
- ++L;
- int k = log(R-L+1) / log(2.0);
- return min(dp[L][k], dp[R-(1<<k)+1][k]);
- }
- };
- Array arr;
- char s[maxn];
- vector<int> v;
- int main(){
- int kase = 0;
- while(scanf("%s", s) == 1 && s[0] != '#'){
- n = strlen(s);
- arr.init();
- for(int i = 0; i < n; ++i)
- arr.s[arr.n++] = s[i] - 'a' + 1;
- arr.s[arr.n++] = 0;
- arr.build_sa(30);
- arr.getHight();
- arr.rmq_init();
- int ans = 0;
- for(int i = 1; i <= n; ++i)
- for(int j = 0; j + i <= n; j += i){
- int k = arr.query(j, j+i);
- int res = k / i + 1;
- int t = j - (i - k % i);
- if(t >= 0 && arr.query(t, t + i) >= k) ++res;
- if(ans < res){
- ans = res;
- v.clear();
- v.push_back(i);
- }
- else if(ans == res) v.push_back(i);
- }
- printf("Case %d: ", ++kase);
- bool ok = true;
- for(int i = 0; i < n && ok; ++i)
- for(int j = 0; j < v.size() && ok; ++j)
- if(arr.sa[i] + v[j] <= n){
- if(arr.query(arr.sa[i], arr.sa[i] + v[j]) + v[j] >= ans * v[j]){
- ok = false;
- for(int k = arr.sa[i], l = 0; l < ans * v[j]; ++l, ++k)
- putchar(s[k]);
- printf("\n");
- }
- }
- }
- return 0;
- }
POJ 3693 Maximum repetition substring (后缀数组+RMQ)的更多相关文章
- POJ 3693 Maximum repetition substring ——后缀数组
重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...
- poj 3693 Maximum repetition substring (后缀数组)
其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...
- poj3693 Maximum repetition substring (后缀数组+rmq)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- POJ3693 Maximum repetition substring 后缀数组
POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- POJ 3693 Maximum repetition substring(最多重复次数的子串)
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10461 Ac ...
- Maximum repetition substring 后缀数组
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7578 Acc ...
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- POJ 3693 Maximum repetition substring(后缀数组)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
随机推荐
- stack-铁轨问题
每辆火车都从A方向驶入车站,再从B方向驶出车站,同时它的车厢可以进行某种形式的重新组合.假设从A方向驶来的火车有n节车厢(n<1000),分别按顺序编号为1,2,...,n.假定在进入车站之前每 ...
- 《python基础教程(第二版)》学习笔记 类和对象(第7章)
<python基础教程(第二版)>学习笔记 类和对象(第7章) 定义类class Person: def setName(self,name): self.name=n ...
- Jboss添加Windows服务,同时定期重启
一.添加成Windows服务 进入目录 \wildfly-9.0.2s - All\bin\service\ 编辑 service.bat,修改一下参数 set SHORTNAME=SAMEXAppS ...
- mysql 数据库使用
1. 常用命令 2. 创建表 create table test ( test_id int, test_price decimal ); 或者 create table test2 as selec ...
- C++判断一个文件是否可以正确打开的代码
/* fopen example */ #include <iostream> #include <conio.h> using namespace std; int main ...
- form 中Enctype=multipart/form-data 的作用
form 中Enctype=multipart/form-data 的作用 ENCTYPE="multipart/form-data"用于表单里有图片上传. <form na ...
- java:练习学校学生
java:练习学校学生 一个学生对应一个学校 一个学校对应多个学生 Student类,School类,Demo测试类 Student: public class Student { private S ...
- I.MX6 FFmpeg 录制视频
/************************************************************************* * I.MX6 FFmpeg 录制视频 * 说明: ...
- [HDU4652]Dice
vjudge 题意 \(m\)面骰子,求 1.连续出现\(n\)个相同的停止: 2.连续出现\(n\)个不同的停止 的期望投骰子次数. \(n,m ≤ 10^6\) sol 首先考虑一个转移式子吧. ...
- bzoj 4765: 普通计算姬 主席树+替罪羊树思想
题目大意: 给定一棵\(n\)个节点的带权树有根树,设\(sum_p\)表示以点\(p\)为根的这棵子树中所有节点的权 计算姬支持下列两种操作: 给定两个整数\(u,v\),修改点\(u\)的权值为\ ...