括号序列
括号序列
题目描述
可怜不喜欢括号序列,但是她发现总是有人喜欢出括号序列的题。
为了让全世界都能感受到她的痛苦,她想要写一个转换器:它能把普通的小写字符串转换成长度相同的合法的括号序列。
在可怜的构思中,这样的转换器需要满足如下两个条件:
1.结果的括号序列必须要是合法的,即左右括号必须要是相匹配的。
2.对于一堆相匹配的左右括号,他们所在的位置原来的小写字母必须相同。
举例来说,对于字符串aabaab,()(())就是一个合法的答案,而()()()不满足第二个条件, (((())不满足第一个条件。
可怜发现对于一个小写字符串,有时候有很多满足条件的括号序列,有些时候一个都没有。
于是可怜给出了一个小写字符串,她想让你帮她算一下,有多少个不同的子串满足能转换成合法的括号序列。
输入
输入一行一个小写字符串s。
输出
输出一行一个整数,表示答案。
solution
首先我们考虑暴力每一个起点,用栈维护。当栈为空时,满足j~i为合法的位置。
效率O(n^2)
那么显然是T了,我们考虑从头开始只维护一个栈,记录下每一个位置的栈的状态。
状态用hash值表示
显然相同状态的栈可以互相贡献,那我们排序一下,统计就行。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll unsigned long long
#define p 998244353
#define maxn 1000006
using namespace std;
int n,id[maxn],top;
char ch[maxn],zh[maxn];
ll s[maxn];
int main()
{
scanf("%s",ch+1);
s[0]=0;n=strlen(ch+1);
for(int i=1;i<=n;i++){
if(top>0&&ch[i]==zh[top]){
s[i]=s[id[top]];top--;
}
else {
zh[++top]=ch[i];id[top]=i-1;
s[i]=s[i-1]*p+ch[i];
}
}
//for(int i=0;i<=n;i++)cout<<s[i]<<endl;
sort(s,s+n+1);
int i=0;
long long ans=0;
while(i<=n){
int j=i;while(s[j]==s[i]&&j<=n)j++;
int l=j-i;
ans=ans+(1LL)*l*(l-1)/2;
i=j;
}
cout<<ans<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构