模拟赛 sutoringu
sutoringu
题意:
询问有多少一个字符串内有多少个个子区间,满足可以分成k个相同的串。
分析:
首先可以枚举一个长度len,表示分成的k个长为len的串。然后从1开始,每len的长度分成一块,分成(n-1)/k+1块,首先可以求出连续的k块的是否是合法。
此时只求了起点是1+len*i的串,还有些起点在块内的没有求。
枚举k-1个相同的块,设这些块为i...j,j-i+1=k。然后与求一下第i块和第i-1块最长后缀,设为a,求一下第j块和第j+1块的最长前缀,设为b。说明如果起点在第i-1块的串,必须是后面a个字符,这些串的终点必须是第j+1块的前b个字符。于是计算一下。
如何求连续的k块是否是一样的?可以求出这连续k块在的rank,然后取一个最大的rank和一个最小的rank,然后求之间的height最小值即可。
复杂度$nlog^2n$。
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
char s[N];
int t1[N], t2[N], c[N], sa[N], rnk[N], ht[N], f[N][], Log[N];
void getsa(int n) {
int m = , i, *x = t1, *y = t2;
for (i = ; i <= m; ++i) c[i] = ;
for (i = ; i <= n; ++i) x[i] = s[i], c[x[i]] ++;
for (i = ; i <= m; ++i) c[i] += c[i - ];
for (i = n; i >= ; --i) sa[c[x[i]]--] = i;
for (int k = ; k <= n; k <<= ) {
int p = ;
for (i = n - k + ; i <= n; ++i) y[++p] = i;
for (i = ; i <= n; ++i) if (sa[i] > k) y[++p] = sa[i] - k;
for (i = ; i <= m; ++i) c[i] = ;
for (i = ; i <= n; ++i) c[x[y[i]]] ++;
for (i = ; i <= m; ++i) c[i] += c[i - ];
for (i = n; i >= ; --i) sa[c[x[y[i]]]--] = y[i];
swap(x, y);
p = ;
x[sa[]] = ;
for (i = ; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i - ]] && y[sa[i] + k] == y[sa[i - ] + k]) ? p - : p ++;
if (p > n) break;
m = p;
}
for (i = ; i <= n; ++i) rnk[sa[i]] = i;
ht[] = ;
int k = ;
for (i = ; i <= n; ++i) {
if (rnk[i] == ) continue;
if (k) k --;
int j = sa[rnk[i] - ];
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k ++;
ht[rnk[i]] = k;
}
for (i = ; i <= n; ++i) f[i][] = ht[i];
for (i = ; i <= n; ++i) Log[i] = Log[i >> ] + ;
for (int j = ; j <= Log[n]; ++j)
for (i = ; i + ( << j) - <= n; ++i)
f[i][j] = min(f[i][j - ], f[i + ( << (j - ))][j - ]);
}
int LCP(int i,int j) {
i = rnk[i], j = rnk[j];
if (i > j) swap(i, j);
i ++;
int k = Log[j - i + ];
return min(f[i][k], f[j - ( << k) + ][k]);
}
int LCP2(int i,int j) {
i ++;
int k = Log[j - i + ];
return min(f[i][k], f[j - ( << k) + ][k]);
} set<int> sk;
int n, k, rev[N]; bool check(int len) {
int l = *sk.begin();
set<int>::iterator it = sk.end(); it --;
int r = *it;
return LCP2(l, r) >= len;
}
int check2(int i,int j,int len) {
if (sk.size() >= && !check(len)) return ;
int a = min(len - , LCP(rev[i - ], rev[i - + len]));
if (j + len > n) return ;
int b = min(len - , LCP(j, j + len));
return max(, b - (len - a) + );
}
int main() {
freopen("sutoringu.in", "r", stdin);
freopen("sutoringu.out", "w", stdout);
n = read(), k = read();
scanf("%s", s + );
s[n + ] = '#';
for (int i = ; i <= n; ++i)
s[i + n + ] = s[n - i + ], rev[n - i + ] = i + n + ;
getsa(n + n + );
LL ans = ;
for (int len = ; len <= n; ++len) {
sk.clear();
for (int i = ; i <= n; i += len) {
sk.insert(rnk[i]);
if (sk.size() > k) sk.erase(rnk[i - len * k]);
if (sk.size() == k) ans += check(len);
}
if (len == ) continue;
sk.clear();
for (int i = len + ; i <= n; i += len) {
sk.insert(rnk[i]);
if (sk.size() > k - ) sk.erase(rnk[i - len * (k - )]);
if (sk.size() == k - ) ans += check2(i - (k - ) * len, i, len);
}
}
cout << ans;
return ;
}
模拟赛 sutoringu的更多相关文章
- 3.27模拟赛 sutoringu(后缀数组)
\(\color{white}{mjt是机房模拟赛独自切过题的唯一的人...}\) (应本人要求删掉惹) \(Description\) 给你\(n,k\)和长为\(n\)的字符串\(s\).一个区间 ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- NOIP第7场模拟赛题解
NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...
- PKUSC 模拟赛 day1 下午总结
下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评 第一题是NOIP模拟赛的原题,随便模拟就好啦 本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ #include<cstd ...
- [GRYZ]寒假模拟赛
写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...
随机推荐
- springcloud 入门 3 (服务之间的调用)
服务调用: 指的是注册到服务端上的客户端之间数据的相互调用问题:服务与服务的通讯是基于http restful的 服务直接调用主要有两种实现:ribbon 和 feign ribbon是实现负载均衡 ...
- PHP多进程编之pcntl_fork
其实PHP是支持并发的,只是平时很少使用而已.平时使用最多的应该是使用PHP-FMP调度php进程了吧. 但是,PHP的使用并不局限于做Web,我们完全也可以使用PHP来进行系统工具类的编程,做监控或 ...
- android的hwc浅析【转】
https://blog.csdn.net/alien75/article/details/39290109 注:本文档基于kk进行分析,着重于概念的精确定义和版本历史演变 一.关于hwc的介绍 广义 ...
- Linux centos6.5 系统语言改成中文简体
有时候上传的文件在linux上ls显示的时乱码,原因可能是系统语言编码问题,以Linux centos6.5为例,解决方法如下: 1.在root(皇帝)权限下更改: 查看当前所有语言环境:locale ...
- 1.3Windows控制台的简单操作:
目录: 1.控制台的打开 2.盘符的跳转 3.跳转到某个文件夹 4.展示文件 5.清屏 6.历史记录 7.拖动添加路径 8.自动补齐 9.正常退出 1.打开控制台:系统图标键 + R,输入cmd,按回 ...
- windows Server 2012/2016 路由和远程访问,PPPOE,ADSL,连接接口时出现一个错误,连接被远程计算机终止
经过查询资料,是由mprddm.dll的bug引起的. 修改位置: 将je修改为jmp. 查找修改位置,可参考 前面的RasGetPortUserData的调用,或者 后面的 字符串 64位dll可使 ...
- XtraEditors六、ListBoxControl、CheckedListBoxControl、ImageListBoxControl
ListBoxControl 效果如下: 示例代码: string[] girlArr = { "面码", "Saber", "Mathilda&qu ...
- 【转】开篇python--明白python文件如何组织,理解建立源文件
在Python 中引用是非常简单的事情,这里需要清楚三个概念就可以了包.模块.类.类这个就不用说了. 模块对应的是一个.py 文件,那么module_name 就是这个文件去掉.py 之后的文件名,p ...
- mac下idea 13 在tomcat 7控制台乱码
在mac或linux下idea 13(可能其它版本也会出现乱码) tomcat 7在输出到控制台的日志中文乱码,解决方式 加一个environment variable, 在如图绿色位置添加 JA ...
- Python glob.md
glob 即使glob API非常简单, 但这个模块包含了很多的功能. 在很多情况下, 尤其是你的程序需要寻找出文件系统中, 文件名匹配特定模式的文件时, 是非常有用的. 如果你需要包含一个特定扩展名 ...