当前位置: 首页 > news >正文

P6000 [CEOI2016] match

洛谷

对于暴力写法,我们很容易想到一个 \(O(n^2)\) 的暴力。

我们可以先从左到右枚举需要配对的字符,然后从后往前去找到一个合法且相同的字符配对。

对于怎样才算合法,我们通过此部分内部是否合法,以及前面是否有已选择的括号判断。

在括号本身是合法的情况下,我们处理右边是否合法,对于本身存在解的串,左边也必定合法,可以自己模拟证明。

那么我们还需要找到上一次配对的右端,从这里从后往前开始枚举。可以选择使用搜索,这样可以直接继承上一步的端点位置,直接开始枚举。

由于枚举位置较少,除了最后一个测试点都能过。

代码:

#include<bits/stdc++.h>
using namespace std;
char s[100005],ans[100005],p[100005];
bool f[100005];
int len,cnt;
signed main(){cin>>s+1;len=strlen(s+1);if(len%2==1){cout<<-1;return 0;}f[len+1]=1;for(int i=1;i<=len;i++){if(f[i])continue;bool flag=0;int w;for(int j=i+1;j<=len+1;j++){if(f[j]){w=j;break;}}for(int j=w-1;j>i;j--){if(cnt==0&&s[j]==s[i]){flag=1;ans[j]=')';f[j]=1;break;}if(!cnt||p[cnt]!=s[j])p[++cnt]=s[j];else cnt--;}if(!flag){cout<<-1;return 0;}ans[i]='(';}cout<<ans+1;return 0;
}

时间复杂度的瓶颈明显在于如何找到合适的配对。

第一种做法是哈希,我们使用字符串哈希记录下当前结点未配对的字符,若字符相同且两个点的字符相同,则可以组成合法的括号,直接二分得到配对即可。

代码:

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int base=131;
char s[100005],ans[100005];
int len,p[100005],top;
ull h[100005],b[100005];
vector<pair<ull,int>> e[30];
void init(){for(int i=len;i>=1;i--){if(top&&s[p[top]]==s[i])top--;else{p[++top]=i;h[top]=h[top-1]*base+s[i];}b[i]=h[top];e[s[i]-97].push_back({b[i],i});}if(top){cout<<-1;exit(0);}for(int i=0;i<26;++i)sort(e[i].begin(),e[i].end());
}
int find(int p,ull v,int x){int l=0,r=e[p].size(),ans;while(l<=r){int mid=l+r>>1;if(e[p][mid].first<v)l=mid+1;else if(e[p][mid].first>v)r=mid-1;else{if(e[p][mid].second>x)r=mid-1;else{l=mid+1;ans=e[p][mid].second;}}}return ans;
}
void dfs(int l,int r){if(l>r)return;ans[l]='(',ans[r]=')';if(r-l==1)return;int x=find(s[l]-97,b[l+1],r);ans[x]=')';dfs(l+1,x-1),dfs(x+1,r);
}
signed main(){cin>>s+1;len=strlen(s+1);init();dfs(1,len);cout<<ans+1;return 0;
}

第二种做法,考虑动态规划,设置 \(dp_{i,j}\) 表示以 \(i\) 为最右端,在一个符号为 \(j\) 且在此之后到 \(i\) 可以组成一个合法括号串的最大位置。

我们可以得到方程式:

\[dp_{i,j}=dp_{dp_{i-1,s_i-97}-1,j} \]

看似复杂实际上很简单,相当于连接了两个括号串。

然后怎么处理答案呢?

我们从暴力方法可以通过搜索得到范围,那么我们知道了右端点位置,就可以用右端点找到一个最靠右的点与左端点进行匹配。

代码:

#include<bits/stdc++.h>
using namespace std;
int len,p[100005],cnt,dp[100005][30];
char s[100005],ans[100005];
bool check(){for(int i=1;i<=len;i++){if(cnt&&p[cnt]==s[i]-'a')cnt--;else p[++cnt]=s[i]-'a';}if(cnt)return true;cnt=0;return false;
}
void dfs(int l,int r){if(l>r)return ;int tmp=dp[r][s[l]-97];ans[l]='(',ans[tmp]=')';dfs(l+1,tmp-1),dfs(tmp+1,r);
}
signed main(){cin>>s+1;len=strlen(s+1);if(check()){cout<<-1;return 0;}for(int i=1;i<=len;i++){for(int j=0;j<26;j++)if(dp[i-1][s[i]-97])dp[i][j]=dp[dp[i-1][s[i]-97]-1][j];dp[i][s[i]-97]=i;}dfs(1,len);cout<<ans+1;return 0;
}
http://www.rkmt.cn/news/75757.html

相关文章:

  • 汽车智能座舱软件、技术、分类介绍
  • 『NAS』在群晖部署图表绘制工具-Draw.io
  • PowerShell TOTP 身份验证器
  • linux 中gzip、bzip2、xz压缩、解压缩
  • Java方法
  • 【Java EE进阶 --- SpringBoot】统一特性处理
  • 2025液体钙权威品牌推荐,首选inne液体钙
  • 2025 年 12 月数粒机厂家权威推荐榜:覆盖防爆/高速/高精度/智能/视觉全自动等新型设备,制药食品农业电子多行业定制化解决方案深度解析
  • 儿童营养选对不踩坑!德国 inne以硬核品质展现品牌价值
  • 2025年12月四面弹面料厂家权威推荐榜:尼龙/涤纶/TR消光等八大品类,揭秘高弹力与舒适度的科技织物奥秘
  • 2025 年 12 月真空自耗电弧炉厂家权威推荐榜:涵盖2.5t/4t/7t真空熔炼炉型,尖端电极自耗技术深度解析与高效选购指南
  • Springboot智慧旅游管理系统6w63eon8(软件+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 【EF Core】“DB First”方案下用编程方式生成数据库模型代码
  • 面向AI时代的操作系统:openEuler在WSL环境下的高效开发实践
  • 2025 最新机器视觉检测服务商 / 厂家 TOP5 评测!智能检测赋能制造升级,权威榜单助力企业选型,智慧工厂设计、建设及管理解决方案
  • 2025年中国五大铝氧化着色生产企业推荐,看哪家工艺水平高
  • 2025年12月中国GEO服务商综合推荐分析:摘星AI引领全球
  • 揭秘WAAP:现代Web应用与API保护的四大核心安全支柱
  • 深入解析:从阿里云大模型服务平台百炼看AI应用集成与实践
  • 2025年中国气力输送厂五大推荐,看哪家技术实力强
  • 在 S2S 场景中理解 On-Behalf-Of (OBO) 流程
  • NetCore使用WCF简单方式
  • .NET Core WebAPI 中使用 MISE + S2S 的三种方式
  • offline meta RL | 论文速读记录
  • 无锡新世源科技有限公司的技术实力怎样?品牌知名度高不高?
  • 2025年比较好的喷射式绞丝染色机/低浴比成衣染色机品牌厂家排行榜
  • 2025年评价高的高粘瓷砖胶最新TOP厂家推荐
  • 2025年质量好的粉末TAIC交联剂行业内口碑厂家排行榜
  • 2025年热门的薄抽同步隐藏轨/全拉同步隐藏轨TOP品牌厂家排行榜
  • 2025年知名的太空梭游乐设施/旋转塔游乐设施高评价厂家推荐榜