CF IndiaHacks 2016 F Paper task 后缀数组
题目链接:http://codeforces.com/problemset/problem/653/F
大意是给出一个只包含'('和')'的括号串,求有多少不同的子串是合法的括号串
解法:对于每一个后缀,需要能够求出这个后缀有多少前缀是合法的括号串,这个可以用O(log n)复杂度的二分来解决。注意,二分的范围并不是整个后缀,因为如果将'('视作+1, ')'视作-1,则一个合法的括号串必须时刻不能小于0。所以可以在ST表上二分出合法范围,在这个范围内去统计有多少合法串(即'('与')'正负相消)。求出一个区间内有多少数字值为x可以对一个保存值和位置的pair数组排序后二分。
那么剩下的问题就是如何去重,由于height数组中记录的是排名相邻的两个后缀的最长公共前缀LCP,那么每一次统计只要根据这个信息减去相应重复统计的数量即可。
下面的代码中统计了两次num,是直接对上述思路的实现,其实是可以合并的。
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set> using namespace std; const int N=+;
char s[N];
int sum[N];
vector< pair<int,int> >v; int preLog2[N];
struct SparseTable {
#define T int
#define MAXN N
static T MIN(T a,T b){return a<b?a:b;}
static T MAX(T a,T b){return a>b?a:b;}
SparseTable() {
if (!preLog2[]){
preLog2[]=;
for (int i=;i<MAXN;i++)
preLog2[i]=preLog2[i>>]+;
}
}
T dp[MAXN][];
T (*cmp) (T,T);
void setMin(){cmp=MIN;}
void setMax(){cmp=MAX;}
void init(int n,T *val) {
for (int i=;i<n;i++)
dp[i][]=val[i];
for (int j=;(<<j)<=n;j++) {
int k=<<(j-);
for (int i=;i+k<n;i++)
dp[i][j]=cmp(dp[i][j-],dp[i+k][j-]);
}
}
T query(int a,int b) {
if (a>b) swap(a,b);
int k=preLog2[b-a+];
return cmp(dp[a][k],dp[b-(<<k)+][k]);
}
#undef MAXN
#undef T
}tab;
struct SuffixArray {
int wa[N], wb[N], cnt[N], wv[N];
int rk[N], height[N];
int sa[N];
bool cmp(int r[], int a, int b, int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void calcSA(char r[], int n, int m) {
int i, j, p, *x = wa, *y = wb;
for (i = ; i < m; ++i) cnt[i] = ;
for (i = ; i < n; ++i) cnt[x[i]=r[i]]++;
for (i = ; i < m; ++i) cnt[i] += cnt[i-];
for (i = n-; i >= ; --i) sa[--cnt[x[i]]] = i;
for (j = , p = ; p < n; j *= , m = p) {
for (p = , i = n - j; i < n; ++i) y[p++] = i;
for (i = ; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = ; i < n; ++i) wv[i] = x[y[i]];
for (i = ; i < m; ++i) cnt[i] = ;
for (i = ; i < n; ++i) cnt[wv[i]]++;
for (i = ; i < m; ++i) cnt[i] += cnt[i-];
for (i = n-; i >= ; --i) sa[--cnt[wv[i]]] = y[i];
for (swap(x, y), p = , x[sa[]] = , i = ; i < n; ++i)
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p- : p++;
}
}
void calcHeight(char r[], int n) {
int i, j, k = ;
for (i = ; i <= n; ++i) rk[sa[i]] = i;
for (i = ; i < n; height[rk[i++]] = k)
for (k?k--:, j = sa[rk[i]-]; r[i+k] == r[j+k]; k++);
}
int lcp(int a,int b,int len) {
if (a==b) return len-a;
int ra=rk[a],rb=rk[b];
if (ra>rb) swap(ra,rb);
return queryST(ra+,rb);
}
int st[N][];
int preLog2[N];
void initST(int n) {
for (int i=;i<=n; i++)
st[i][]=height[i];
for (int j=;(<<j)<=n; j++) {
int k=<<(j-);
for (int i=; i+k<=n; i++)
st[i][j]=min(st[i][j-],st[i+k][j-]);
}
preLog2[]=;
for(int i=;i<=n;i++){
preLog2[i]=preLog2[i>>]+;
}
}
int queryST(int a,int b) {
if (a>b) swap(a,b);
int dis=b-a+;
int k=preLog2[dis];
return min(st[a][k],st[b-(<<k)+][k]);
}
void solve(int n) {
long long ret=;
for (int i=;i<=n;i++) {
if (s[sa[i]]==')') continue;
int l=sa[i],h=n-,p=n;
while (l<=h) {
int m=(l+h)>>;
if (tab.query(l,m)<sum[sa[i]]-) {
p=m;
h=m-;
}
else
l=m+;
}
p--;
int num=upper_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-,p))-lower_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-,sa[i]));
ret+=num;
int preR=min(sa[i]+height[i]-,p);
num=upper_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-,preR))-lower_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-,sa[i]));
ret-=num;
}
printf("%I64d\n",ret);
}
}suf; int main() {
int n;
scanf("%d",&n);
scanf("%s",s);
sum[]=(s[]=='(')?:-;
for (int i=;i<n;i++)
sum[i]=sum[i-]+((s[i]=='(')?:-);
for (int i=;i<n;i++) {
v.push_back(make_pair(sum[i],i));
}
sort(v.begin(),v.end());
tab.setMin();
tab.init(n,sum);
suf.calcSA(s,n+,);
suf.calcHeight(s,n);
suf.solve(n);
return ;
}
CF IndiaHacks 2016 F Paper task 后缀数组的更多相关文章
- [CF653F] Paper task - 后缀数组,线段树,vector
		[CF653F] Paper task Description 给定一个括号序列,统计合法的本质不同子串的个数. Solution 很容易想到,只要在传统统计本质不同子串的基础上修改一下即可. 考虑经 ... 
- NOI 2016 优秀的拆分 (后缀数组+差分)
		题目大意:给你一个字符串,求所有子串的所有优秀拆分总和,优秀的拆分被定义为一个字符串可以被拆分成4个子串,形如$AABB$,其中$AA$相同,$BB$相同,$AB$也可以相同 作为一道国赛题,95分竟 ... 
- 2016多校联合训练4 F - Substring  后缀数组
		Description ?? is practicing his program skill, and now he is given a string, he has to calculate th ... 
- 2016暑假多校联合---Substring(后缀数组)
		2016暑假多校联合---Substring Problem Description ?? is practicing his program skill, and now he is given a ... 
- CF 504E	Misha and LCP on Tree(树链剖分+后缀数组)
		题目链接:http://codeforces.com/problemset/problem/504/E 题意:给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. ... 
- CF 504E Misha and LCP on Tree——后缀数组+树链剖分
		题目:http://codeforces.com/contest/504/problem/E 树链剖分,把重链都接起来,且把每条重链的另一种方向的也都接上,在这个 2*n 的序列上跑后缀数组. 对于询 ... 
- CF 504 E —— Misha and LCP on Tree —— 树剖+后缀数组
		题目:http://codeforces.com/contest/504/problem/E 快速查询LCP,可以用后缀数组,但树上的字符串不是一个序列: 所以考虑转化成序列—— dfs 序! 普通的 ... 
- CSU1656: Paper of FlyBrother(后缀数组)
		Description FlyBrother is a superman, therefore he is always busy saving the world. To graduate fro ... 
- CF(427D-Match & Catch)后缀数组应用
		题意:给两个字符串,求一个最短的子串.使得这个子串在两个字符串中出现的次数都等于1.出现的定义为:能够重叠的出现. 解法:后缀数组的应用.从小枚举长度.假设一个长度len合法的话:则一定存在这个样的s ... 
随机推荐
- Spring学习笔记①
			我觉得Spring之所以发展的好,主要是理论研究与实践是并轨的,能跟得上时代的步伐,尤其是基础理论的研究(可能是最近看三体看多了,对基础理论非常崇拜).微服务的实现啊,RESTful的实现,对应的Sp ... 
- 1644: [Usaco2007 Oct]Obstacle Course 障碍训练课
			1644: [Usaco2007 Oct]Obstacle Course 障碍训练课 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 383 Solved ... 
- curl  javaSSm框架中传入json数组的格式方法
			curl与java结合传入get.post,head请求, 比如: curl的地址: curl -l 127.0.0.1:8080/spacobj/core/do?acid=100 -H " ... 
- linux上执行 xhost unable to open display
			linux下执行xhost命令报错:unable to open display,解决方法,linux 下通过xhost进入图形界面,经常会出现报错"unable to open disp ... 
- linux 根分区扩展
			linux根分区扩容 今天网站上传图片出问题了,一开始还以为是程序问题,后来发现原来是服务器存储空间不够,明明有200G的磁盘空间,没理由这么快就用完,查了一下分区情况,原来有两块磁盘,根分区只挂载在 ... 
- windows系统下安装composer
			使用安装程序安装 这是将 Composer 安装在你机器上的最简单的方法. 下载并且运行 Composer-Setup.exe,它将安装最新版本的 Composer 安装完成后,将composer的b ... 
- Nginx网站使用CDN之后禁止用户真实IP访问的方法
			做过面向公网WEB的运维人员经常会遇见恶意扫描.拉取.注入等图谋不轨的行为,对于直接对外的WEB服务器,我们可以直接通过 iptables .Nginx 的deny指令或是程序来ban掉这些恶意请求. ... 
- javaEE与JSP基础
			JSP基础 1. jsp的作用: * Servlet: > 缺点:不适合设置html响应体,需要大量的response.getWriter().print("<html ... 
- sass.scss简单入门
			最近研究了一下sass和scss,清晰结构化,在某些地方的确强大,所以写了一篇入门教程,大概15分钟左右就能明白基本原理 什么是sass(css预处理器) Sass官网上是这样描述sass的,sass ... 
- 【Hexo】(一)使用HEXO配置环境,创建Hello World
			现场直播,呵呵,就是我完成一步,就记录一下: 一.配置环境 1.安装 Node 下载地址:Node.js 2.安装 Git(win环境下) 下载地址:Git Git 绑定 GitHub账户: ①打开G ... 
