您的位置:首页 > 其它

codeforces 653F

2016-04-15 11:31 295 查看

原题

原题链接

题目大意

给你一个长度为n≤5∗105n\leq 5*10^5的只含有左右括号字符串,问,有多少个不同的合法的字串满足正确的括号序。

满足条件的括号序:

1) A=”()”

2) (A)

3) AA

解题思路

我们可以把((当成+1,把))当成-1,那么可以做一个前缀和sis_i,如果要求以ii位置开头的合法的括号序的个数就是求有多少个i<j≤ni满足sj=si−1,∀i≤k≤j,sk≥si−1s_j=s_{i-1},\forall i\leq k \leq j ,s_k\geq s_{i-1}.

这个方法是没有去重的,但是我们可以发现,我们用后缀数组求了heightheight之后,jj的可选范围,就变成了i+heighti+1≤j≤ni+height_i+1 \leq j \leq n,其他条件一样。

现在问题就是要满足∀i≤k≤j,sk≥si−1\forall i\leq k \leq j ,s_k\geq s_{i-1},这个条件了。我们可以用Rmq来维护区间的ss最小值,然后二分判断最大可选的jj,在哪个位置就行了。

参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 500005
#define maxsq 22
#define pb(i) push_back(i)
#define ll long long
using namespace std;

vector <int> p[maxn*2];

int height[maxn],sa[maxn],rank[maxn],x[maxn],y[maxn],wv[maxn],wss[maxn];

int n,s[maxn];

char ch[maxn];

int Log[maxn],f[maxn][maxsq];

ll ans;

bool compare(int *rank,int i,int j,int l){
return rank[i]==rank[j] && rank[i+l]==rank[j+l];
}

void SA(){
int i,j,m=')'+1,p;
fo(i,1,n) wss[x[i]=ch[i]]++;
fo(i,1,m) wss[i]+=wss[i-1];
fo(i,1,n) sa[wss[x[i]]--]=i;
for(j=1,p=0;p<n;m=p,j*=2) {
for(p=0,i=n-j+1;i<=n;i++) y[++p]=i;
for(i=1;i<=n;i++) if (sa[i]-j>0) y[++p]=sa[i]-j;
for(i=1;i<=n;i++) wv[i]=x[y[i]];
for(i=1;i<=m;i++) wss[i]=0;
for(i=1;i<=n;i++) wss[wv[i]]++;
for(i=1;i<=m;i++) wss[i]+=wss[i-1];
for(i=n;i>=1;i--) sa[wss[wv[i]]--]=y[i];
swap(x,y);
for(x[sa[1]]=1,p=1,i=2;i<=n;i++)
x[sa[i]]=compare(y,sa[i-1],sa[i],j) ? p : ++p;
}
}

void get_height(){
fo(i,1,n) rank[sa[i]]=i;
int j,k=0;
for(int i=1;i<=n;height[rank[i++]]=k)
for(k ? k-- : 0,j=sa[rank[i]-1];ch[i+k]==ch[j+k];k++);
}

int calc(int x,int y){
int dis=y-x+1;
return min(f[x][Log[dis]],f[y-(1 << Log[dis])+1][Log[dis]]);
}

int main(){
scanf("%d",&n);
char c=getchar();
while (c!='(' && c!=')') c=getchar();
fo(i,1,n) {
ch[i]=c;
if (c=='(') s[i]=s[i-1]+1;
else s[i]=s[i-1]-1;
f[i][0]=s[i];
c=getchar();
p[s[i]+n].pb(i);
}
fo(i,2,n) Log[i]=Log[i >> 1]+1;
fo(i,1,Log
)
fo(j,1,n-(1 << i)+1) f[j][i]=min(f[j][i-1],f[j+(1 << (i-1))][i-1]);
SA();
get_height();
fo(i,1,n) {
int w=sa[i];
if (ch[w]==')') continue;
int fr=w+height[i];
if (fr>n) continue;
int to=w;
int l=w,r=n;
while (l<=r) {
int mid=(l+r) >> 1;
if (calc(w,mid)>=s[w-1]) {
to=mid;
l=mid+1;
} else r=mid-1;
}
if (fr>to) continue;
ans+=upper_bound(p[s[w-1]+n].begin(),p[s[w-1]+n].end(),to)-lower_bound(p[s[w-1]+n].begin(),p[s[w-1]+n].end(),fr);
}
printf("%I64d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: