当前位置: 首页 > 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.jsqmd.com/news/65216/

相关文章:

  • MultiButton移植记录
  • Hugging Face 论文页面功能指南
  • 北京上门回收老酒名酒茅台五粮液
  • P5202 [USACO19JAN] Redistricting P
  • 详细介绍:数据结构5:二叉树
  • Excel 公式
  • P10602 [CEOI 2009] Harbingers
  • 2025 Newest Autel BMW G-Chassis IMMO Add Key (1-Year License) for IM508/IM608/IM1/IM2
  • Go 1.25 发布:性能、器具与生态的全面进化
  • P6173 [USACO16FEB] Circular Barn P
  • 为数字文明奠基:论通译院-价值星图-叙事舞台架构作为价值实践的元操作系统
  • 实用指南:OSG多视口与多通道渲染核心技术解析
  • P8313 [COCI 2021/2022 #4] Izbori
  • 汽车智能座舱软件、技术、分类介绍
  • 2025 最新智能制造服务商 / 厂家 TOP5 评测!科技赋能 + 全周期服务权威推荐榜单发布,引领智慧工厂建设新生态
  • 『NAS』在群晖部署图表绘制工具-Draw.io
  • CF762E Radio stations
  • grep 常用功能
  • 2025 最新工业自动化服务商 / 厂家 TOP5 评测!科技赋能 + 全周期服务权威榜单发布,引领智慧工厂建设新生态
  • 2025 最新智慧工厂建设服务商/厂家 TOP5 评测!科技赋能+全周期服务权威推荐榜单发布,引领智能制造新生态
  • why windows is worst
  • 4pcs Launch LTR-05 TPMS Sensor Tool 315MHz 433MHz - Metal/Rubber for European/American Cars
  • Get Lifetime Free Launch X431 ADAS Calibration for PAD VII/Pro5/Pro3S+/Pro3/APEX
  • 儿童补钙不盲选!从钙源到配方,儿童钙剂选购全指南
  • 2025年ChatGPT优化排名公司推荐:AI驱动下的SEO新选择
  • 【拓补排序 TB_sort】P4017 最大食物链计数
  • 2025年深圳GEO优化公司推荐:AI驱动时代的流量突围伙伴
  • 2025年11月儿童营养品牌测评指南——选对不踩坑
  • 2025年深圳AI搜索排名优化公司推荐
  • 【AI大模型技术】2.神经网络 - 教程