题意:

给定一个串\(s\),\(s\)必有一个最大循环节的连续子串\(ss\),问最大循环次数是多少

思路:

我们可以知道,如果一个长度为\(L\)的子串连续出现了两次及以上,那么必然会存在\(s[0]、s[L]、s[2L] \cdots s[L * k]\)中至少有两个连续的位置是相同的,然后看字母\(s[L * i]和s[L * (i + 1)]\)往前往后最多能匹配多远,记住总长度\(len\),那么最大循环次数为\((len / L) + 1\)。

参考:

SPOJ 687. Repeats(后缀数组)

代码:

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 50000 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 11;
const int MOD = 1e9 + 7;
using namespace std;//下标从0开始
int str[maxn];  //str[n]赋值一个最小值0,其他大于0
int t1[maxn], t2[maxn], c[maxn];
int sa[maxn];   //排名为i的后缀下标
int rk[maxn];   //后缀下标为i的排名
int height[maxn];   //sa[i]与sa[i - 1]的LCP
int mm[maxn];
int dp[maxn][30];
bool cmp(int *r, int a, int b, int l){return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int *str, int n, int m){n++;int i, j, p, *x = t1, *y = t2;for(i = 0; i < m; i++) c[i] = 0;for(i = 0; i < n; i++) c[x[i] = str[i]]++;for(i = 1; i < m; i++) c[i] += c[i - 1];for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;for(j = 1; j <= n; j <<= 1){p = 0;for(i = n - j; i < n; i++) y[p++] = i;for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;for(i = 0; i < m; i++) c[i] = 0;for(i = 0; i < n; i++) c[x[y[i]]]++;for(i = 1; i < m; i++) c[i] += c[i - 1];for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];swap(x, y);p = 1; x[sa[0]] = 0;for(i = 1; i < n; i++)x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++;if(p >= n) break;m = p;}int k = 0;n--;for(i = 0; i <= n; i++) rk[sa[i]] = i;for(i = 0; i < n; i++){if(k) k--;j = sa[rk[i] - 1];while(str[i + k] == str[j + k]) k++;height[rk[i]] = k;}
}
void initRMQ(int n){mm[0] = -1;for(int i = 1; i <= n; i++){dp[i][0] = height[i];mm[i] = ((i & (i - 1)) == 0)? mm[i - 1] + 1 : mm[i - 1];}for(int j = 1; j <= mm[n]; j++)for(int i = 1; i + (1 << j) - 1 <= n; i++)dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
int RMQ(int L, int R){int k = mm[R - L + 1];return min(dp[L][k], dp[R - (1 << k) + 1][k]);
}
int LCP(int i, int j){   //求后缀i和j的LCP最长公共前缀int L = rk[i], R = rk[j];if(L > R) swap(L, R);L++;return RMQ(L, R);
}int main(){int T;scanf("%d", &T);while(T--){int n;scanf("%d", &n);for(int i = 0; i < n; i++){char ss[2];scanf("%s", ss);str[i] = ss[0] - 'a' + 1;}str[n] = 0;da(str, n, 3);initRMQ(n);int ans = 1;for(int i = 1; i < n; i++){for(int j = 0; j + i < n; j += i){int len = LCP(j, j + i);int times = len / i + 1;int pos = j - (i - len % i);if(pos >= 0){len = LCP(pos, pos + i);times = max(times, len / i + 1);}ans = max(ans, times);}}printf("%d\n", ans);}return 0;
}

转载于:https://www.cnblogs.com/KirinSB/p/11262768.html

SPOJ REPEATS Repeats (后缀数组 + RMQ:子串的最大循环节)题解相关推荐

  1. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  2. SPOJ 7258 SUBLEX 后缀数组_二分答案_前缀和

    SPOJ 7258 SUBLEX 后缀数组_二分答案_前缀和 Code: #include <cstdio> #include <algorithm> #include < ...

  3. hdu 2459 (后缀数组+RMQ)

    题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...

  4. URAL - 1297 Palindrome(后缀数组+RMQ)

    题目链接:点击查看 题目大意:给出一个字符串,求出最长的回文子串 题目分析:如果用以往的方法求,不可避免的都需要枚举所有子串,时间复杂度就已经到达了O(n),而后缀数组可以通过O(n)预处理后得到所有 ...

  5. hdu 5008 Boring String Problem(后缀数组+rmq)

    题目链接:hdu 5008 Boring String Problem 题意: 给你一个字符串,有q个询问,每次询问该字符串所有的子串中字典序第k小的是哪个串,输出位置,如果有多个位置,输出最靠左的那 ...

  6. HDU - 6194 string string string(后缀数组+RMQ+容斥)

    题目链接:点击查看 题目大意:给出一个字符串和一个数字 k,问字符串中出现次数恰好等于 k 次的字串有多少个 题目分析:在跑完后缀数组后,我们可以用sa数组求解,具体做法是枚举起点,找长度为 k 的s ...

  7. HDU - 4552 怪盗基德的挑战书(后缀数组+RMQ/KMP+dp)

    题目链接:点击查看 题目大意:给出一个字符串,统计每个前缀在字符串中出现的次数之和 题目分析:可以直接先用后缀数组跑出来height,再用RMQ跑出来任意两个后缀的height,我们可以将题意转换为求 ...

  8. HDU 6194 string string string 后缀数组 + RMQ(线段树)

    传送门:HDU6194 题意:问给定字符串中有多少种出现k次的子串. 思路:首先想到后缀数组经典问题,求出现不少于k次的子串的最大长度,类似的这题肯定就是在height数组上搞事情啦. 将height ...

  9. URAL 题目1297. Palindrome(后缀数组+RMQ求最长回文子串)

    1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The "U.S. Robots" HQ has just ...

  10. POJ - 3693 Maximum repetition substring(后缀数组+RMQ)

    题目链接:点击查看 题目大意:给出一个字符串,求出字符串中 重复次数最多的连续重复子串 ,如果有多个答案,输出字典序最小的 题目分析:又是一个模板题,这里放一个大佬的博客,讲的很清楚: https:/ ...

最新文章

  1. Git011--分支管理策略
  2. PLSQL_性能优化系列04_Oracle Optimizer优化器
  3. 阅读《Android 从入门到精通》(29)——四大布局
  4. 第三次学JAVA再学不好就吃翔(part82)--泛型
  5. springmvc ztree 实现权限菜单的展示
  6. 2010年5月系统集成项目管理工程师上午试卷参考答案(讨论版)
  7. mysql 修改表名的方法:sql语句
  8. 普中51控制火焰传感器_传感器检测:以后,电动车充电会变成这样
  9. 头条三面: String.valueOf、toString()、(String)强转,有啥区别?
  10. composer切换源_composer的安装 及 常用命令(切换源等)
  11. 学渣的c#复习手记 类 一
  12. html插入swf自动播放,html嵌入播放器,flv视频播放器 Flvplayer.swf 可自动播放参数说明...
  13. 台式计算机常用的网卡类型,台式机无线网卡如何查看型号
  14. java毕业生设计学生管理部门信息共享交流系统计算机源码+系统+mysql+调试部署+lw
  15. 软件信息安全杂志《Information Security》2011年11月期下载
  16. C#加密和解密PDF文件
  17. 工作内存与主内存是什么,硬件层面的存储架构是什么样,线程的实现原理是什么
  18. activated钩子函数
  19. LRUCache算法
  20. Displaytag 使用简介

热门文章

  1. 0028-如何在CDH未启用认证的情况下安装及使用Sentry
  2. WPF自定义控件(一)の控件分类
  3. linux下,如何迁移mysql数据库存放目录。利用软连接简单快捷实现移动到home数据盘下...
  4. HDU2504 又见GCD
  5. python类库26[web2py之介绍]
  6. 新的域名,新的空间,这里不再更新了。
  7. js练习——动态控制表格中得行
  8. HackingTeam重磅炸弹: 估值超1000万美金带有军火交易性质的木马病毒以及远控源码泄露
  9. 鸿蒙来了!能否与安卓、iOS三足鼎立?
  10. 没学好 Netty ,要凉?