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

Codeforces 2144F Bracket Groups 题解 [ 紫 ] [ AC 自动机 ] [ DP ] [ 构造 ]

Bracket Groups:赛时猜出来用 ACAM,结果没猜到结论,我是糖比。

首先判掉一些 corner,如果出现了 \(\texttt{()}\) 为单个字符串,则一定无解。

发现后面不太好做,所以可以套路地猜一猜答案上界,发现最多只需要分成两组。具体地,考虑往极端情况构造,弄出下面两种括号串:

  • \(\texttt{((((((} \cdots\texttt{))))))}\)
  • \(\texttt{()()()} \cdots\texttt{()()()}\)

考虑证明,如果 \(s\) 不是这两个串中任意一个串的子串,则放哪一组都可以。如果 \(s\) 为第一个串的子串,那么 \(s\)一定含有两个相同且相邻的字符(一种 corner 是 \(\texttt{)(}\) 的情况,此时也会放到第一组),而这是不可能出现在第二个串中的。如果 \(s\) 为第一个串的子串则也是同理的。

剩下的只需要考虑能否被一个括号串全部包含即可。这是个经典的 ACAM 上 DP 的问题。\(dp_{i, j, k}\) 表示考虑到第 \(i\) 个字符,括号串前缀和为 \(j\),ACAM 上在节点 \(k\) 处是否可行,然后转移的时候记录一下前驱即可。最后反过来搜一遍构造出方案。

时间复杂度 \(O(nk^3)\)

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi = pair<int, int>;
const int N = 55, V = 3005;
int n, m, ch[V][2], idx, tag[V], ne[V];
int s[N][N], slen[N];
char ts[N];
void insert(int id)
{int p = 0;for(int i = 1; i <= slen[id]; i++){if(ch[p][s[id][i]] == 0) ch[p][s[id][i]] = ++idx;p = ch[p][s[id][i]];}tag[p] = 1;
}
vector<int> g[V];
void dfs(int u)
{for(auto v : g[u]){tag[v] |= tag[u];dfs(v);}
}
void build()
{queue<int> q;for(int i = 0; i < 2; i++){if(ch[0][i]) q.push(ch[0][i]);}while(!q.empty()){int u = q.front();q.pop();for(int i = 0; i < 2; i++){int v = ch[u][i];if(v) { ne[v] = ch[ne[u]][i]; q.push(v); }else ch[u][i] = ch[ne[u]][i];}}for(int i = 1; i <= idx; i++) g[ne[i]].push_back(i);dfs(0);
}
bitset<V> dp[N][N];
tuple<int, int, int> pre[N][N][V];
char ans[N];
vector<int> ans2, ans3;
void construct(int p)
{int i = m, j = 0;while(i){tuple<int, int, int> tmp = pre[i][j][p];ans[i] = (get<1>(tmp) - j > 0 ? ')' : '(');j = get<1>(tmp);p = get<2>(tmp);i--;}cout << 1 << "\n";cout << ans + 1 << "\n";cout << n << "\n";for(int i = 1; i <= n; i++) cout << i << " ";
}
int main()
{//freopen("sample.in", "r", stdin);//freopen("sample.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m;for(int i = 1; i <= n; i++){cin >> ts + 1;slen[i] = strlen(ts + 1);if(slen[i] == 2 && ts[1] == '(' && ts[2] == ')'){cout << "-1";return 0;}for(int j = 1; j <= slen[i]; j++)s[i][j] = (ts[j] == '(' ? 1 : 0);insert(i);}build();dp[0][0][0] = 1;for(int i = 0; i < m; i++)for(int j = 0; j <= m; j++)for(int k = 0; k <= idx; k++){if(dp[i][j][k] == 0) continue;if(tag[ch[k][0]] == 0 && j - 1 >= 0){dp[i + 1][j - 1][ch[k][0]] = 1;pre[i + 1][j - 1][ch[k][0]] = {i, j, k};}if(tag[ch[k][1]] == 0){dp[i + 1][j + 1][ch[k][1]] = 1;pre[i + 1][j + 1][ch[k][1]] = {i, j, k};}                }for(int i = 0; i <= idx; i++){if(dp[m][0][i]){construct(i);return 0;}}cout << "2\n";for(int i = 1; i <= m; i++) {if(i & 1) cout << "(";else cout << ")";}cout << "\n";for(int i = 1; i <= n; i++){int mn = 0, mx = 0, now = 0;for(int j = 1; j <= slen[i]; j++){if(s[i][j] == 0) now--;else now++;mn = min(mn, now);mx = max(mx, now);}if(mx - mn >= 2) ans2.push_back(i);else ans3.push_back(i);}cout << ans2.size() << "\n";for(auto itm : ans2) cout << itm << " ";cout << "\n";for(int i = 1; i <= m / 2; i++) cout << "(";for(int i = 1; i <= m / 2; i++) cout << ")";cout << "\n";cout << ans3.size() << "\n";for(auto itm : ans3) cout << itm << " ";cout << "\n";    return 0;
}
http://www.hskmm.com/?act=detail&tid=8983

相关文章:

  • Java进制,数据类型拓展Unicode编码学习
  • 9月18日总结
  • 【转】[IDEA] 调试时怎么判断使用哪个配置文件
  • 软件工程学习日志2025.9.18
  • U3D动作游戏开发读书笔记--3.1 物理系统详解(上)
  • 一个联名款电子产品的技术实现和诞生
  • https://uupdump.net/
  • JOISC
  • 20250918 之所思 - 人生如梦
  • 初赛知识点复盘
  • WPF使用Cef加载Vue3页面问题
  • IP子网划分
  • curl与wget
  • 用 Go 语言与 Tesseract OCR 实现英文数字验证码识别
  • lc1031-两个非重叠子数组的最大和
  • Segment Analytics-iOS SDK - 专业用户行为追踪解决方案
  • 我对 WPF 动摇时的选择:.NET Framework 4.6.2+WPF+Islands+UWP+CompostionApi - 行人-
  • 使用 Rust 与 Tesseract OCR 识别英文数字验证码
  • 别迷茫了!计算机大一新生这样做,四年后远超同龄人 - 编程实战派
  • 解决ifconfig命令没有显示ens33 finalshell连接不上虚拟机
  • 什么情况下需要用到xargs
  • Office 2024安装包专业增强版超详细下载安装教程
  • 关于 pdfminer 的安装 - 指南
  • c/c++实现有栈协程
  • Day17冒泡排序
  • 高阶 INTJ 5w4 整合到 8,是完整的过程,从研究到实用(豆包)
  • 几B大模型的空间存储大小
  • hbase安装与配置
  • 发喷山火(volcano)+CF2119F Volcanic Eruptions 解题报告
  • matlab免费下载安装激活教程(附安装包下载)MATLAB R2025a超详细下载安装教程