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; }
相关文章推荐
- CTF进阶之路1——virtualbox安装
- 产品经理 产品设计师常用软件
- 面试感悟----一名3年工作经验的程序员应该具备的技能
- JAVA生成二维码
- 详解C#中的反射
- 错误:namenode无法自动切换成active
- 补第十一次课作业(法律法规、标准规范、职业道德)
- ntp服务
- Android Support v4、v7、v13、v14、v17的区别和应用场景
- BestCoder Round #74 Shortest Path
- Android listview与adapter用法详解
- SDL音频播放
- Linux下文件描述符
- qt4.键盘方向键
- Monitoring an IBM JVM with VisualVM
- IIS中使用Microsoft.Office.Interop.Excel 常见问题:RPC 服务器不可用。 (异常来自 HRESULT:0x800706BA) 的异常。等
- GPS模块数据放入谷歌地图显示,不准
- java随机生成字符串算法
- 第十二次课作业(需求管理、外包管理、组织级与大项目管理)
- 导航栏使用不透明的图片时,控制器view的y值