题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的。

析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2].....这些点中相邻的两个,然后向前和向后匹配,

看看最大的匹配多大,然后把所有的答案记录下来,最后再从sa中开始枚举答案,第一个就是字典序最小的。

代码如下:

  1. #pragma comment(linker, "/STACK:1024000000,1024000000")
  2. #include <cstdio>
  3. #include <string>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <iostream>
  7. #include <cstring>
  8. #include <set>
  9. #include <queue>
  10. #include <algorithm>
  11. #include <vector>
  12. #include <map>
  13. #include <cctype>
  14. #include <cmath>
  15. #include <stack>
  16. #include <sstream>
  17. #define debug() puts("++++");
  18. #define gcd(a, b) __gcd(a, b)
  19. #define lson l,m,rt<<1
  20. #define rson m+1,r,rt<<1|1
  21. #define freopenr freopen("in.txt", "r", stdin)
  22. #define freopenw freopen("out.txt", "w", stdout)
  23. using namespace std;
  24.  
  25. typedef long long LL;
  26. typedef unsigned long long ULL;
  27. typedef pair<int, int> P;
  28. const int INF = 0x3f3f3f3f;
  29. const LL LNF = 1e16;
  30. const double inf = 0x3f3f3f3f3f3f;
  31. const double PI = acos(-1.0);
  32. const double eps = 1e-8;
  33. const int maxn = 1e5 + 10;
  34. const int mod = 1e9 + 7;
  35. const int dr[] = {-1, 0, 1, 0};
  36. const int dc[] = {0, 1, 0, -1};
  37. const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
  38. int n, m;
  39. const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  40. const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  41. inline bool is_in(int r, int c){
  42. return r >= 0 && r < n && c >= 0 && c < m;
  43. }
  44.  
  45. struct Array{
  46. int sa[maxn], s[maxn], t[maxn], t2[maxn];
  47. int r[maxn], h[maxn], c[maxn], dp[maxn][20];
  48. int n;
  49.  
  50. void init(){
  51. n = 0; memset(sa, 0, sizeof sa);
  52. }
  53.  
  54. void build_sa(int m){
  55. int *x = t, *y = t2;
  56. for(int i = 0; i < m; ++i) c[i] = 0;
  57. for(int i = 0; i < n; ++i) ++c[x[i] = s[i]];
  58. for(int i = 1; i < m; ++i) c[i] += c[i-1];
  59. for(int i = n-1; i >= 0; --i) sa[--c[x[i]]] = i;
  60.  
  61. for(int k = 1; k <= n; k <<= 1){
  62. int p = 0;
  63. for(int i = n-k; i < n; ++i) y[p++] = i;
  64. for(int i = 0; i < n; ++i) if(sa[i] >= k) y[p++] = sa[i] - k;
  65. for(int i = 0; i < m; ++i) c[i] = 0;
  66. for(int i = 0; i < n; ++i) ++c[x[y[i]]];
  67. for(int i = 1; i < m; ++i) c[i] += c[i-1];
  68. for(int i = n-1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i];
  69.  
  70. swap(x, y);
  71. p = 1; x[sa[0]] = 0;
  72. for(int i = 1; i < n; ++i)
  73. x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
  74. if(p >= n) break;
  75. m = p;
  76. }
  77. }
  78.  
  79. void getHight(){
  80. int k = 0;
  81. for(int i = 0; i < n; ++i) r[sa[i]] = i;
  82. for(int i = 0; i < n; ++i){
  83. if(k) --k;
  84. int j = sa[r[i]-1];
  85. while(s[i+k] == s[j+k]) ++k;
  86. h[r[i]] = k;
  87. }
  88. }
  89.  
  90. void rmq_init(){
  91. for(int i = 1; i <= n; ++i) dp[i][0] = h[i];
  92. for(int j = 1; (1<<j) <= n; ++j)
  93. for(int i = 1; i + (1<<j) <= n; ++i)
  94. dp[i][j] = min(dp[i][j-1], dp[i+(1<<j-1)][j-1]);
  95. }
  96.  
  97. int query(int L, int R){
  98. L = r[L]; R = r[R];
  99. if(L > R) swap(L, R);
  100. ++L;
  101. int k = log(R-L+1) / log(2.0);
  102. return min(dp[L][k], dp[R-(1<<k)+1][k]);
  103. }
  104. };
  105. Array arr;
  106. char s[maxn];
  107. vector<int> v;
  108.  
  109. int main(){
  110. int kase = 0;
  111. while(scanf("%s", s) == 1 && s[0] != '#'){
  112. n = strlen(s);
  113. arr.init();
  114. for(int i = 0; i < n; ++i)
  115. arr.s[arr.n++] = s[i] - 'a' + 1;
  116. arr.s[arr.n++] = 0;
  117. arr.build_sa(30);
  118. arr.getHight();
  119. arr.rmq_init();
  120. int ans = 0;
  121. for(int i = 1; i <= n; ++i)
  122. for(int j = 0; j + i <= n; j += i){
  123. int k = arr.query(j, j+i);
  124. int res = k / i + 1;
  125. int t = j - (i - k % i);
  126. if(t >= 0 && arr.query(t, t + i) >= k) ++res;
  127. if(ans < res){
  128. ans = res;
  129. v.clear();
  130. v.push_back(i);
  131. }
  132. else if(ans == res) v.push_back(i);
  133. }
  134.  
  135. printf("Case %d: ", ++kase);
  136. bool ok = true;
  137. for(int i = 0; i < n && ok; ++i)
  138. for(int j = 0; j < v.size() && ok; ++j)
  139. if(arr.sa[i] + v[j] <= n){
  140. if(arr.query(arr.sa[i], arr.sa[i] + v[j]) + v[j] >= ans * v[j]){
  141. ok = false;
  142. for(int k = arr.sa[i], l = 0; l < ans * v[j]; ++l, ++k)
  143. putchar(s[k]);
  144. printf("\n");
  145. }
  146. }
  147. }
  148. return 0;
  149. }

  

POJ 3693 Maximum repetition substring (后缀数组+RMQ)的更多相关文章

  1. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

  2. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  3. poj3693 Maximum repetition substring (后缀数组+rmq)

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

  4. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

  5. POJ3693 Maximum repetition substring [后缀数组 ST表]

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

  6. POJ 3693 Maximum repetition substring(最多重复次数的子串)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10461   Ac ...

  7. Maximum repetition substring 后缀数组

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

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

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

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

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

随机推荐

  1. stack-铁轨问题

    每辆火车都从A方向驶入车站,再从B方向驶出车站,同时它的车厢可以进行某种形式的重新组合.假设从A方向驶来的火车有n节车厢(n<1000),分别按顺序编号为1,2,...,n.假定在进入车站之前每 ...

  2. 《python基础教程(第二版)》学习笔记 类和对象(第7章)

    <python基础教程(第二版)>学习笔记 类和对象(第7章) 定义类class Person:    def setName(self,name):        self.name=n ...

  3. Jboss添加Windows服务,同时定期重启

    一.添加成Windows服务 进入目录 \wildfly-9.0.2s - All\bin\service\ 编辑 service.bat,修改一下参数 set SHORTNAME=SAMEXAppS ...

  4. mysql 数据库使用

    1. 常用命令 2. 创建表 create table test ( test_id int, test_price decimal ); 或者 create table test2 as selec ...

  5. C++判断一个文件是否可以正确打开的代码

    /* fopen example */ #include <iostream> #include <conio.h> using namespace std; int main ...

  6. form 中Enctype=multipart/form-data 的作用

    form 中Enctype=multipart/form-data 的作用 ENCTYPE="multipart/form-data"用于表单里有图片上传. <form na ...

  7. java:练习学校学生

    java:练习学校学生 一个学生对应一个学校 一个学校对应多个学生 Student类,School类,Demo测试类 Student: public class Student { private S ...

  8. I.MX6 FFmpeg 录制视频

    /************************************************************************* * I.MX6 FFmpeg 录制视频 * 说明: ...

  9. [HDU4652]Dice

    vjudge 题意 \(m\)面骰子,求 1.连续出现\(n\)个相同的停止: 2.连续出现\(n\)个不同的停止 的期望投骰子次数. \(n,m ≤ 10^6\) sol 首先考虑一个转移式子吧. ...

  10. bzoj 4765: 普通计算姬 主席树+替罪羊树思想

    题目大意: 给定一棵\(n\)个节点的带权树有根树,设\(sum_p\)表示以点\(p\)为根的这棵子树中所有节点的权 计算姬支持下列两种操作: 给定两个整数\(u,v\),修改点\(u\)的权值为\ ...