题目链接

题意

求字符串SSS中满足子串可以复制KKK次得到的字串的数量,不位置字串相同的字符串分开计算

思路

看题解补完的这道题
枚举循环节的长度XXX,从头找到字符串SSS中连续出现循环节的最多的字串,假设当前求得的区间是[L,R][L, R][L,R],lcp(R+1,L)lcp(R+1, L)lcp(R+1,L)即为字串向后可以扩展的长度(长度小于XXX),相反求向前可以扩展的位置。这样每次可以得到循环节为XXX的最长的连续区间,每次累计答案即可

#include <bits/stdc++.h>
const int maxn = 1e6 + 5;
using namespace std;
struct SuffixArray{ // 下标int cntA[maxn], cntB[maxn], A[maxn], B[maxn];int Sa[maxn], tsa[maxn], height[maxn], Rank[maxn];int n, dp[maxn][21];void init(char *buf, int len) { // 预处理,sa,rank,heightn = len;for (int i = 0; i < 128; ++i) cntA[i] = 0;for (int i = 1; i <= n; ++i) cntA[(int)buf[i]]++;for (int i = 1; i < 128; ++i) cntA[i] += cntA[i-1];for (int i = n; i >= 1; --i) Sa[ cntA[(int)buf[i]]-- ] = i;Rank[ Sa[1] ] = 1;for (int i = 2; i <= n; ++i) {Rank[Sa[i]] = Rank[Sa[i-1]];if (buf[Sa[i]] != buf[Sa[i-1]]) Rank[Sa[i]]++;}for (int l = 1; Rank[Sa[n]] < n; l <<= 1) {for (int i = 0; i <= n; ++i) cntA[i] = 0;for (int i = 0; i <= n; ++i) cntB[i] = 0;for (int i = 1; i <= n; ++i) {cntA[ A[i] = Rank[i] ]++;cntB[ B[i] = (i + l <= n) ? Rank[i+l] : 0]++;}for (int i = 1; i <= n; ++i) cntB[i] += cntB[i-1];for (int i = n; i >= 1; --i) tsa[ cntB[B[i]]-- ] = i;for (int i = 1; i <= n; ++i) cntA[i] += cntA[i-1];for (int i = n; i >= 1; --i) Sa[ cntA[A[tsa[i]]]-- ] = tsa[i];Rank[ Sa[1] ] = 1;for (int i = 2; i <= n; ++i) {Rank[Sa[i]] = Rank[Sa[i-1]];if (A[Sa[i]] != A[Sa[i-1]] || B[Sa[i]] != B[Sa[i-1]]) Rank[Sa[i]]++;}}for (int i = 1, j = 0; i <= n; ++i) {if (j) --j;int tmp = Sa[Rank[i] - 1];while (i + j <= n && tmp + j <= n && buf[i+j] == buf[tmp+j]) ++j;height[Rank[i]] = j;}}void st() {for (int i = 1; i <= n; ++i) {dp[i][0] = height[i];}for (int j = 1; j <= log2(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 len = r - l + 1;int x = log2(len);return min(dp[l][x], dp[r - (1 << x) + 1][x]);}int lcp(int x, int y) { // 最长公共前缀int l = Rank[x];int r = Rank[y];if (l > r) swap(l, r);return rmq(l+1, r);}
}L, R;
int work(int l, int r, int p, int len, int k) { // 计算前后缀,前后扩展,累计答案int rt = L.lcp(l, r+1); // 向右扩展int lt = R.lcp(len+1-r, len+1-l+1); // 向前扩展r += rt;l -= lt;return max(0, r-l+1 - k*p + 1); // 返回kp的个数
}
char s[maxn], t[maxn];
int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T;scanf("%d", &T);while (T--) {int k;long long ans = 0;scanf("%d%s", &k, t+1);int len = strlen(t+1);if (k == 1) {ans = 1ll * (1 + len) * len / 2;printf("%lld\n", ans);continue;}strcpy(s+1, t+1);reverse(t+1, t+1+len);s[0] = t[0] = '&';L.init(s, len); L.st();R.init(t, len); R.st();for (int i = 1; i <= len/2; ++i) { // 枚举循环节int last = 1;for (int j = i+1; j <= len; j += i) { // 找到最长的循环节为i的字符串if (L.lcp(last, j) >= i) continue;ans += work(last, j-1, i, len, k);if (j+i-1 <= len) last = j;else last = 0;}if (last) ans += work(last, len, i, len, k);}printf("%lld\n", ans);}return 0;
}

HDU - 6661 Acesrc and String Theory (后缀数组)相关推荐

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

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

  2. HDU - 5008 Boring String Problem(后缀数组+二分)

    题目链接:点击查看 题目大意:给出一个字符串,接下来给出 q 个询问,每次询问字符串中第 k 大的子串,要求输出该字串的左右端点,如果有多个答案,输出左端点最小的一个 题目分析:因为在求出后缀数组后, ...

  3. HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)

    Problem 求字符串 S 中严格出现 k 次的子串个数 k≥1k\ge 1 |S|≤105|S|\le 10^5 ∑|S|≤2×106\sum |S| \le 2\times 10^6 Idea ...

  4. zoj 1905 Power String(后缀数组)

     题意:给定一个字符串L,已知这个字符串是由某个字符串S 重复R 次而得到的,求R 的最大值. 做法比较简单,穷举字符串S 的长度k,然后判断是否满足.判断的时候, 先看字符串L 的长度能否被k ...

  5. HDU 5008 Boring String Problem ( 后缀数组求本质不同第k大子串)

    Boring String Problem Zeronera题解 预处理sum数组记录不同字符串的个数,即sum[i] = n- sa[i] + 1 -height[i] + sum[i-1] (n为 ...

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

    题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...

  7. HDU - 5030 Rabbit's String(后缀数组+二分)

    题目链接:点击查看 题目大意:给出一个字符串,现在要求将其分为不大于k个连续的子串,对于每个子串求出字典序最大的子串,现在要求所有子串的最大子串的最大值最小,输出这个最大子串 题目分析:最大值最小,标 ...

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

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

  9. HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机

    题意:给出一个字符串,求出出现了恰好k次的子串的个数. 题解:恰好k次 = 至少k次 - 至少k+1次.答案转化为求至少出现k次的子串个数统计.构造好后缀数组以及很重要的Height数组之后.用一个k ...

最新文章

  1. ajax传值的url,JQuery ajax url传值与data传值的区别
  2. 商汤62篇论文入选CVPR 2019,一览五大方向最新研究进展
  3. python轨迹追踪、全链路日志追踪trace_id实现
  4. 【python教程入门学习】用pyecharts绘制带动画效果的“时间轮播图
  5. NotificationManagerService使用详解与原理分析(一)
  6. android点击运行后无法显示设备,Android仿真器除了黑屏外什么都不显示,adb设备显示“设备离线”...
  7. git clone 报错 Clone failed: Authentication failed for
  8. 学习hashtable,处理“海量”数据
  9. 46muduo库使用示例(五)
  10. 转换为正整数_进制之间的转换
  11. 软件测试 | 手把手教你快速掌握 Monkey 工具,指令参数+APK集合测试
  12. 无名接口.php,李无名
  13. FusionCharts 分类以及各个属性参数列表
  14. 微信小程序热潮或渐趋冷静
  15. mysql可视化界面创建表_mysql安装及可视化界面
  16. 铁路计算机工程师论文,工程技术类有关论文格式模板,关于铁路工程师职文2016年相关论文范本...
  17. Matlab实现时间序列预测
  18. Y2K问题和2038问题
  19. 分享15款精美的免费 HTML5 网站模板
  20. 毕业了,异地恋只能分手吗?

热门文章

  1. Mellanox 8亿美元收购EZchip
  2. 简单工厂之简单模型(uml)
  3. 【Python数据挖掘课程】五.线性回归知识及预测糖尿病实例
  4. 汇编基础知识之输入输出
  5. App设计灵感之十二组精美的手机健康监测App设计案例
  6. 《数据库原理与应用》(第三版)第9章 事务与并发控制 基础 习题参考答案
  7. 并发编程——线程——理论知识
  8. django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or later is required (found 3.7.17).
  9. 2016年第七届蓝桥杯 - 国赛 - Java大学C组 - I. 路径之谜
  10. 信息学奥赛一本通(C++)在线评测系统——基础(二)基础算法 —— 1312:【例3.4】昆虫繁殖