HDU - 6661 Acesrc and String Theory (后缀数组)
题目链接
题意
求字符串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 (后缀数组)相关推荐
- hdu 5008 Boring String Problem(后缀数组+rmq)
题目链接:hdu 5008 Boring String Problem 题意: 给你一个字符串,有q个询问,每次询问该字符串所有的子串中字典序第k小的是哪个串,输出位置,如果有多个位置,输出最靠左的那 ...
- HDU - 5008 Boring String Problem(后缀数组+二分)
题目链接:点击查看 题目大意:给出一个字符串,接下来给出 q 个询问,每次询问字符串中第 k 大的子串,要求输出该字串的左右端点,如果有多个答案,输出左端点最小的一个 题目分析:因为在求出后缀数组后, ...
- 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 ...
- zoj 1905 Power String(后缀数组)
题意:给定一个字符串L,已知这个字符串是由某个字符串S 重复R 次而得到的,求R 的最大值. 做法比较简单,穷举字符串S 的长度k,然后判断是否满足.判断的时候, 先看字符串L 的长度能否被k ...
- HDU 5008 Boring String Problem ( 后缀数组求本质不同第k大子串)
Boring String Problem Zeronera题解 预处理sum数组记录不同字符串的个数,即sum[i] = n- sa[i] + 1 -height[i] + sum[i-1] (n为 ...
- HDU 6194 string string string (后缀数组+线段树)
题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...
- HDU - 5030 Rabbit's String(后缀数组+二分)
题目链接:点击查看 题目大意:给出一个字符串,现在要求将其分为不大于k个连续的子串,对于每个子串求出字典序最大的子串,现在要求所有子串的最大子串的最大值最小,输出这个最大子串 题目分析:最大值最小,标 ...
- HDU - 6194 string string string(后缀数组+RMQ+容斥)
题目链接:点击查看 题目大意:给出一个字符串和一个数字 k,问字符串中出现次数恰好等于 k 次的字串有多少个 题目分析:在跑完后缀数组后,我们可以用sa数组求解,具体做法是枚举起点,找长度为 k 的s ...
- HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机
题意:给出一个字符串,求出出现了恰好k次的子串的个数. 题解:恰好k次 = 至少k次 - 至少k+1次.答案转化为求至少出现k次的子串个数统计.构造好后缀数组以及很重要的Height数组之后.用一个k ...
最新文章
- ajax传值的url,JQuery ajax url传值与data传值的区别
- 商汤62篇论文入选CVPR 2019,一览五大方向最新研究进展
- python轨迹追踪、全链路日志追踪trace_id实现
- 【python教程入门学习】用pyecharts绘制带动画效果的“时间轮播图
- NotificationManagerService使用详解与原理分析(一)
- android点击运行后无法显示设备,Android仿真器除了黑屏外什么都不显示,adb设备显示“设备离线”...
- git clone 报错 Clone failed: Authentication failed for
- 学习hashtable,处理“海量”数据
- 46muduo库使用示例(五)
- 转换为正整数_进制之间的转换
- 软件测试 | 手把手教你快速掌握 Monkey 工具,指令参数+APK集合测试
- 无名接口.php,李无名
- FusionCharts 分类以及各个属性参数列表
- 微信小程序热潮或渐趋冷静
- mysql可视化界面创建表_mysql安装及可视化界面
- 铁路计算机工程师论文,工程技术类有关论文格式模板,关于铁路工程师职文2016年相关论文范本...
- Matlab实现时间序列预测
- Y2K问题和2038问题
- 分享15款精美的免费 HTML5 网站模板
- 毕业了,异地恋只能分手吗?
热门文章
- Mellanox 8亿美元收购EZchip
- 简单工厂之简单模型(uml)
- 【Python数据挖掘课程】五.线性回归知识及预测糖尿病实例
- 汇编基础知识之输入输出
- App设计灵感之十二组精美的手机健康监测App设计案例
- 《数据库原理与应用》(第三版)第9章 事务与并发控制 基础 习题参考答案
- 并发编程——线程——理论知识
- django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or later is required (found 3.7.17).
- 2016年第七届蓝桥杯 - 国赛 - Java大学C组 - I. 路径之谜
- 信息学奥赛一本通(C++)在线评测系统——基础(二)基础算法 —— 1312:【例3.4】昆虫繁殖