单调栈+set+后缀数组

一道奇妙的题

这道题如果对于每个询问$r$是固定的,那么就很简单了,可惜并不是

由于r会变化,那么对于两个子串$[i...r],[j...r]$,他们的大小关系随着r的变化也会变化,使得我们不能直接预处理答案

所以我们把询问离线,把每个询问按照r分类,通过考虑r的变化来完成询问

对于两个后缀$[i...r],[j...r],(i<j)$,设他们的$lcp=l$,那么当$l∈[j,j+l-1]$时,$[i...r]>[j...r]$,当$r=j+l$时,则变成$[i...r]<[j...r]$,因为$s[i+l]<s[j+l]$(假设)

我们称这样的两个后缀为$i$伴随$j$。

那么我们对答案维护一个set,里面存着一些后缀,保证后缀当前的大小单调递减,这样我们就可以每次快速询问答案。

但是由于$r$的变化每次大小关系会改变,也就是我们要把一些后缀删掉

那么我们再维护一个单调栈,这里存的是严格的后缀大小,这个单调栈是为了给每个新加入的后缀求出哪些后缀伴随他

那么如果当前的栈顶是大于新的后缀,$break$,否则标记$top$伴随$i$,并且记录当$i$,也就是$r=i+lcp$时删除栈顶

每次删除一个元素时,伴随他的元素也应该删除,所以每次$dfs$删除即可,并在$set$里删除

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int N = 1e5 + ;
int n, k, m, top;
int rnk[N], tmp[N], sa[N], ans[N], vis[N], st[N], h[N][], Log[N];
char s[N];
set<int> S;
vector<pair<int, int> > v[N];
vector<int> del[N], g[N];
bool cmp(int i, int j) {
if(rnk[i] != rnk[j]) {
return rnk[i] < rnk[j];
}
int ri = i + k <= n ? rnk[i + k] : -;
int rj = j + k <= n ? rnk[j + k] : -;
return ri < rj;
}
void dfs(int u) {
vis[u] = ;
S.erase(u);
for(int i = ; i < g[u].size(); ++i) {
if(!vis[g[u][i]]) {
dfs(g[u][i]);
}
}
}
void SA() {
for(int i = ; i <= n; ++i) {
sa[i] = i;
rnk[i] = s[i];
}
for(k = ; k <= n; k <<= ) {
sort(sa + , sa + n + , cmp);
tmp[sa[]] = ;
for(int i = ; i <= n; ++i) {
tmp[sa[i]] = tmp[sa[i - ]] + (cmp(sa[i - ], sa[i]));
}
for(int i = ; i <= n; ++i) {
rnk[i] = tmp[i];
}
}
for(int i = ; i <= n; ++i) {
rnk[sa[i]] = i;
}
int d = ;
for(int i = ; i <= n; ++i) {
if(rnk[i] <= ) {
continue;
}
int j = sa[rnk[i] - ];
if(d) {
--d;
}
for(; i + d <= n && j + d <= n; ++d) {
if(s[i + d] != s[j + d]) {
break;
}
}
h[rnk[i] - ][] = d;
}
for(int j = ; j <= ; ++j) {
for(int i = ; i + ( << j) - <= n; ++i) {
h[i][j] = min(h[i][j - ], h[i + ( << (j - ))][j - ]);
}
}
}
int rmq(int l, int r) {
if(l == r) {
return n - l + ;
}
l = rnk[l];
r = rnk[r];
if(l > r) {
swap(l, r);
}
--r;
int x = Log[r - l + ];
return min(h[l][x], h[r - ( << x) + ][x]);
}
int main() {
scanf("%s%d", s + , &m);
n = strlen(s + );
for(int i = ; i <= n; ++i) {
Log[i] = Log[i >> ] + ;
}
SA();
for(int i = ; i <= m; ++i) {
int l, r;
scanf("%d%d", &l, &r);
v[r].push_back(make_pair(l, i));
}
for(int i = ; i <= n; ++i) {
S.insert(i);
while(top) {
int lcp = rmq(st[top], i);
if(s[st[top] + lcp] > s[i + lcp]) {
break;
}
del[i + lcp].push_back(st[top]);
g[i].push_back(st[top]);
--top;
}
st[++top] = i;
for(int j = ; j < del[i].size(); ++j) {
if(!vis[del[i][j]]) {
dfs(del[i][j]);
}
}
for(int j = ; j < v[i].size(); ++j) {
pair<int, int> x = v[i][j];
ans[x.second] = *S.lower_bound(x.first);
}
}
for(int i = ; i <= m; ++i) {
printf("%d\n", ans[i]);
}
return ;
}

bzoj4453的更多相关文章

  1. 【BZOJ4453】cys就是要拿英魂! 后缀数组+单调栈+set

    [BZOJ4453]cys就是要拿英魂! Description pps又开始dota视频直播了!一群每天被pps虐的蒟蒻决定学习pps的操作技术,他们把pps在这局放的技能记录了下来,每个技能用一个 ...

随机推荐

  1. CentOS Python 安装MySQL-python

    一.安装mysql yum list | grep mysql >>yum install -y mysql-server mysql mysql-devel CentOS 7的yum源中 ...

  2. A charge WIFI point base on airbase-ng+dhcp+lamp+wiwiz

    Make wifi as a hot point Make a script echo $0 $1 case $1 in "start") sleep 1 ifconfig wla ...

  3. 2015年多校联合训练第一场OO’s Sequence(hdu5288)

    题意:给定一个长度为n的序列,规定f(l,r)是对于l,r范围内的某个数字a[i],都不能找到一个相应的j使得a[i]%a[j]=0.那么l,r内有多少个i,f(l,r)就是几. 问全部f(l,r)的 ...

  4. 网页直播、微信直播技术解决方案:EasyNVR与EasyDSS流媒体服务器组合之区分不同场景下的easynvr

    近期遇到好多客户咨询关于实现微信直播.或者是将直播页面集成进入自己项目中. 该方案的主要目的:完成在公网一直进行内网摄像头的RTMP/HLS直播! 实现方案的具体实现: EasyNVR+EasyDSS ...

  5. 小程序WePY入门(一)

    全局安装或更新WePY命令行工具 npm install wepy-cli -g 在开发目录中生成Demo开发项目 wepy new myproject 切换至项目目录 cd myproject 开启 ...

  6. 替代或者与 Redis 配合存储十亿级别列表的数据.

    http://ssdb.io/docs/zh_cn/index.html 用户案例 如果你在生产环境中使用 SSDB, 欢迎你给我发邮件(ssdb#udpwork.com), 我很愿意把你加入到下面的 ...

  7. Thinkphp2.2 config.inc.php常用配置

    CHECK_FILE_CASE -- windows环境下面的严格检查大小写. /* 项目设定 */    'APP_DEBUG'    => false, // 是否开启调试模式    'AP ...

  8. 剑指Offer:矩形覆盖【N1】

    剑指Offer:矩形覆盖[N1] 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 题目思考 我们先把2*8的 ...

  9. 借助node.js + mysql 学习基础ajax~

    很多小白不知道ajax怎么学,所以就弄了个node后台模拟下基本的ajax请求. 环境要求是安装node~ 先上linkMysql.js var mysql = require('mysql') va ...

  10. 冷门PHP函数汇总

    概述 整理一些日常生活中基本用不到的PHP函数,也可以说在框架内基本都内置了,无需我们去自行使用的函数.量不多.后续在日常开发中如遇到更多的冷门,会更新本文章 sys_getloadavg 获取系统的 ...