[bzoj3879]SvT_后缀数组_RMQ_单调栈
SvT bzoj-3879
题目大意:给定一个字符串。每次询问给定$t$个位置,求两两位置开头的后缀的$LCP$之和。
注释:$1\le length\le 5\cdot 10^5$,$\sum t\le 3\cdot 10^6$。
想法:
不难想到构建后缀数组。
进而我们的问题就转化成了给定序列上一些位置求这些位置两两之间区间最小值的和。
对$ht$数组建立$ST$表。
接下来的过程可以用单调栈维护。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
using namespace std; typedef long long ll;
int n,m,wa[N],wb[N],wv[N],sa[N],height[N],rank[N],r[N],Ws[N];
char ch[N];
int f[21][N],L[N],vis[N],s[N],g[N];
int v[3000050],Q[3000050];
ll dp[N];
inline char nc()
{
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd()
{
int x=0; char c=nc();
while(c<'0'||c>'9') c=nc();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=nc();
return x;
}
inline int rc()
{
char c=nc();
while(c<'a'||c>'z') c=nc();
return (int)c;
} void build_sa()
{
m=27;
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) Ws[i]=0;
for(i=0;i<n;i++) Ws[x[i]=r[i]]++;
for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
for(i=n-1;i>=0;i--) sa[--Ws[x[i]]]=i;
for(p=j=1;p<n;j<<=1,m=p)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) Ws[i]=0;
for(i=0;i<n;i++) Ws[wv[i]]++;
for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
for(i=n-1;i>=0;i--) sa[--Ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++)
{
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
for(i=1;i<n;i++) rank[sa[i]]=i;
for(i=p=0;i<n-1;height[rank[i++]]=p)
for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++);
}
int get_min(int l,int r)
{
int len=L[r-l+1];
return min(f[len][l],f[len][r-(1<<len)+1]);
}
void ST()
{
int i,j;
for(i=2;i<=n;i++) L[i]=L[i>>1]+1;
for(i=1;i<=n;i++) f[0][i]=height[i];
for(i=1;(1<<i)<=n;i++)
{
for(j=1;j+(1<<i)-1<=n;j++) f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
}
}
bool cmp(int x,int y)
{
return rank[x]<rank[y];
}
int main()
{
int T;
n=rd(); T=rd();
int i;
for(i=0;i<n;i++) r[i]=rc()-'a'+1;
r[n++]=0;
int tot=0;
build_sa(); n--; ST();
while(T--)
{
tot++;
int t=0;
v[0]=rd();
int j;
for(j=1;j<=v[0];j++)
{
v[j]=rd();
v[j]--;
if(vis[v[j]]==tot) {j--; v[0]--;}
vis[v[j]]=tot;
}
sort(v+1,v+v[0]+1,cmp);
for(j=1;j<v[0];j++)
{
g[j]=get_min(rank[v[j]]+1,rank[v[j+1]]);
}
t=1; Q[1]=0;
long long ans=0;
for(j=1;j<v[0];j++)
{
while(t&&g[Q[t]]>g[j]) t--;
dp[j]=dp[Q[t]]+1ll*(j-Q[t])*g[j];
ans+=dp[j];
Q[++t]=j;
}
printf("%lld\n",ans);
}
return 0;
}
小结:后缀数组真好玩。
[bzoj3879]SvT_后缀数组_RMQ_单调栈的更多相关文章
- poj3415 Common Substrings(后缀数组,单调栈 | 后缀自动机)
[题目链接] http://poj.org/problem?id=3415 [题意] A与B长度至少为k的公共子串个数. [思路] 基本思想是将AB各个后缀的lcp-k+1的值求和.首先将两个字符串拼 ...
- [bzoj3238][Ahoi2013]差异_后缀数组_单调栈
差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然 ...
- 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈
P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...
- Gym - 102028H Can You Solve the Harder Problem? (后缀数组+RMQ+单调栈)
题意:求一个序列中本质不同的连续子序列的最大值之和. 由于要求“本质不同”,所以后缀数组就派上用场了,可以从小到大枚举每个后缀,对于每个sa[i],从sa[i]+ht[i]开始枚举(ht[0]=0), ...
- 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)
补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...
- 【POJ3415】Common Substrings(后缀数组,单调栈)
题意: n<=1e5 思路: 我的做法和题解有些不同 题解是维护A的单调栈算B的贡献,反过来再做一次 我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去 式子展开之后 ...
- 【BZOJ3238】差异(后缀数组,单调栈)
题意: 思路:显然len(t[i])+len(t[j])这部分的和是一定的 那么问题就在于如何快速求出两两之间lcp之和 考虑将它们排名后用SA可以很方便的求出lcp,且对答案没有影响,因为形式都是数 ...
- POJ.3145.Common Substrings(后缀数组 倍增 单调栈)
题目链接 \(Description\) 求两个字符串长度不小于k的公共子串对数. \(Solution\) 求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}( ...
- BZOJ3879:SvT(后缀数组,单调栈,ST表)
Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...
随机推荐
- 开发一个 Web App 必须了解的那些事
在过去的一年里,我在从头开始开发我的第一个重要的Web应用.经验教会了很多以前不知道的东西,特别是在安全性和用户体验方面. 值得一提的是,我上一次尝试构建的任何合理复杂性是在2005年.所以,在安全防 ...
- R Programming week 3-Loop functions
Looping on the Command Line Writing for, while loops is useful when programming but not particularly ...
- R Programming week2 Control Structures
Control Structures Control structures in R allow you to control the flow of execution of the program ...
- Node.js——环境变量
- PowerShell让系统可以执行.ps1文件,开机,关机,在线时间 , Function自定义函数
Function Get-ComputerUptimeHistory { $q=' <QueryList> <Query Id="0" Path="Sy ...
- 迅为iTOP-4418嵌入式开发板初体验
iTOP-4418开发板预装 Android4.4.4 系统, 支持9.7 寸.7 寸.4.3 寸屏幕. 参数:核心板参数 尺寸 50mm*60mm高度 核心板连接器为1.5mmCPU ARM Cor ...
- Java方法注释模板
普通方法 /** * ${todo} * @author: SYJP * @version 创建时间:${date} */ 覆盖方法 /** * @Title: ${enclosing_method} ...
- 类方法__setattr__,__delattr__,__getattr__
__getattr__,_delattr_,_getattr_ class Foo: x = 1 def __init__(self, y): self.y = y def __getattr__(s ...
- Java 斜杠 与 反斜杠
除号 /(数字键盘的斜杠)网址 /(数字键盘的斜杠)文件地址 \转义 \正则表达式 \
- 原生 js 上传图片
js <!doctype html> <html> <head> <meta charset="utf-8"> <title& ...