传送门

题意:

给出\(s,t\)两个合法括号序列,现在找到一个长度最小的合法的序列\(p\),使得\(s,t\)都为其子序列。

思路:

  • 考虑\(dp:dp[i][j][d]\)表示第一个串在\(i\),第二个串在\(j\),答案串左括号和右括号之差为\(d\)时的最短长度。
  • 那么转移时枚举下一位转移即可。
  • 还需要考虑一点细节:若当前\(d=0\),但是下一位为)时,我们需要先\(dp[i][j][0]\)向\(dp[i][j][1]\)转移,即在答案串中添加一个(来匹配。
  • 最后的答案即为\(min\{dp[n][m][d]+d\}\),若\(d>0\)时,我们还需要在答案串后面添加\(d\)个)来使其合法。
  • 输出路径时转移时记录一下前驱,然后根据\(d\)来找到当前应为哪个括号。

代码如下:

  1. /*
  2. * Author: heyuhhh
  3. * Created Time: 2019/12/13 11:40:50
  4. */
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <cstring>
  8. #include <vector>
  9. #include <cmath>
  10. #include <set>
  11. #include <map>
  12. #include <queue>
  13. #include <iomanip>
  14. #define MP make_pair
  15. #define fi first
  16. #define se second
  17. #define sz(x) (int)(x).size()
  18. #define all(x) (x).begin(), (x).end()
  19. #define INF 0x3f3f3f3f
  20. #define Local
  21. #ifdef Local
  22. #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  23. void err() { std::cout << '\n'; }
  24. template<typename T, typename...Args>
  25. void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  26. #else
  27. #define dbg(...)
  28. #endif
  29. void pt() {std::cout << '\n'; }
  30. template<typename T, typename...Args>
  31. void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
  32. using namespace std;
  33. typedef long long ll;
  34. typedef pair<int, int> pii;
  35. //head
  36. const int N = 200 + 5;
  37. struct node {
  38. int i, j, k;
  39. };
  40. node pre[N][N][N << 1];
  41. int dp[N][N][N << 1];
  42. int n, m;
  43. char s[N], t[N];
  44. void run(){
  45. cin >> (s + 1) >> (t + 1);
  46. n = strlen(s + 1);
  47. m = strlen(t + 1);
  48. memset(dp, INF, sizeof(dp));
  49. dp[0][0][0] = 0;
  50. for(int i = 0; i <= n; i++) {
  51. for(int j = 0; j <= m; j++) {
  52. if(i == n && j == m) break;
  53. for(int k = 0; k < N; k++) if(dp[i][j][k] != INF) {
  54. if(s[i + 1] == t[j + 1]) {
  55. if(s[i + 1] == ')') {
  56. if(k == 0) {
  57. if(dp[i][j][k + 1] > dp[i][j][k] + 1) {
  58. dp[i][j][k + 1] = dp[i][j][k] + 1;
  59. pre[i][j][k + 1] = node {i, j, k};
  60. }
  61. }
  62. if(dp[i + 1][j + 1][k - 1] > dp[i][j][k] + 1) {
  63. dp[i + 1][j + 1][k - 1] = dp[i][j][k] + 1;
  64. pre[i + 1][j + 1][k - 1] = node {i, j, k};
  65. }
  66. } else if(s[i + 1] == '(') {
  67. if(dp[i + 1][j + 1][k + 1] > dp[i][j][k] + 1) {
  68. dp[i + 1][j + 1][k + 1] = dp[i][j][k] + 1;
  69. pre[i + 1][j + 1][k + 1] = node {i, j, k};
  70. }
  71. }
  72. } else {
  73. if(s[i + 1] == ')') {
  74. if(k == 0) {
  75. if(dp[i][j][k + 1] > dp[i][j][k] + 1) {
  76. dp[i][j][k + 1] = dp[i][j][k] + 1;
  77. pre[i][j][k + 1] = node {i, j, k};
  78. }
  79. }
  80. if(dp[i + 1][j][k - 1] > dp[i][j][k] + 1) {
  81. dp[i + 1][j][k - 1] = dp[i][j][k] + 1;
  82. pre[i + 1][j][k - 1] = node {i, j, k};
  83. }
  84. } else if(s[i + 1] == '(') {
  85. if(dp[i + 1][j][k + 1] > dp[i][j][k] + 1) {
  86. dp[i + 1][j][k + 1] = dp[i][j][k] + 1;
  87. pre[i + 1][j][k + 1] = node {i, j, k};
  88. }
  89. }
  90. if(t[j + 1] == ')') {
  91. if(k == 0) {
  92. if(dp[i][j][k + 1] > dp[i][j][k] + 1) {
  93. dp[i][j][k + 1] = dp[i][j][k] + 1;
  94. pre[i][j][k + 1] = node {i, j, k};
  95. }
  96. }
  97. if(dp[i][j + 1][k - 1] > dp[i][j][k] + 1) {
  98. dp[i][j + 1][k - 1] = dp[i][j][k] + 1;
  99. pre[i][j + 1][k - 1] = node {i, j, k};
  100. }
  101. } else if(t[j + 1] == '(') {
  102. if(dp[i][j + 1][k + 1] > dp[i][j][k] + 1) {
  103. dp[i][j + 1][k + 1] = dp[i][j][k] + 1;
  104. pre[i][j + 1][k + 1] = node {i, j, k};
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }
  111. int Min = INF;
  112. node ans;
  113. for(int i = 0; i < N; i++) {
  114. if(dp[n][m][i] + i < Min) {
  115. Min = dp[n][m][i] + i;
  116. ans = node {n, m, i};
  117. }
  118. }
  119. //for(int i = 400; i < 410; i++) {
  120. //cout << dp[1][3][i] << '\n';
  121. //}
  122. string res = "";
  123. node now = ans, last;
  124. while(1) {
  125. last = pre[now.i][now.j][now.k];
  126. //dbg(now.i, now.j, now.k, dp[now.i][now.j][now.k]);
  127. if(last.k > now.k) res += ")";
  128. else res += "(";
  129. now = last;
  130. if(now.i == 0 && now.j == 0 && now.k == 0) break;
  131. }
  132. reverse(res.begin(), res.end());
  133. for(int i = 0; i < ans.k; i++) res += ")";
  134. cout << res << '\n';;
  135. }
  136. int main() {
  137. ios::sync_with_stdio(false);
  138. cin.tie(0); cout.tie(0);
  139. cout << fixed << setprecision(20);
  140. run();
  141. return 0;
  142. }

【cf1272】F. Two Bracket Sequences的更多相关文章

  1. 【AtCoder】ARC092 D - Two Sequences

    [题目]AtCoder Regular Contest 092 D - Two Sequences [题意]给定n个数的数组A和数组B,求所有A[i]+B[j]的异或和(1<=i,j<=n ...

  2. 【python】f.write()写入中文出错解决办法

    一个出错的例子 #coding:utf-8 s = u'中文' f = open("test.txt","w") f.write(s) f.close() 原因 ...

  3. 【原创】leetCodeOj --- Repeated DNA Sequences 解题报告

    原题地址: https://oj.leetcode.com/problems/repeated-dna-sequences/ 题目内容: All DNA is composed of a series ...

  4. 【LeetCode】187. Repeated DNA Sequences

    题目: All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: " ...

  5. MT【248】$f(x)=\dfrac{1}{x-1}+\dfrac{1}{x-b}$的性质

    探讨函数$f(x)=\dfrac{1}{x-a}+\dfrac{1}{x-b}$其中$a<b$的几个性质 分析:对称性:关于$(\dfrac{a+b}{2},0)$证明提示:$f(x)+f(a+ ...

  6. 【ARC066】F - Contest with Drinks Hard

    题解 我写的斜率维护,放弃了我最擅长的叉积维护,然后发现叉积维护也不会爆long long哦-- 一写斜率维护我的代码就会莫名变长而且难写--行吧 我们看这题 推了推式子,发现这是个斜率的式子,但是斜 ...

  7. 【HDU4734】F(x) 【数位dp】

    题意 先定义了一个函数F(X)=An*2^n-1+An-1*2^n-2+.....+A1*1.其中Ai为X的第i位的值.对于每组数据给出了两个整数A,B.问不超过B的数中有多少的F值是不超过F(A)的 ...

  8. 【hdu4734】F(x) 数位dp

    题目描述 对于一个非负整数 $x=​​\overline{a_na_{n-1}...a_2a_1}$ ,设 $F(x)=a_n·2^{n-1}+a_{n-1}·2^{n-2}+...+a_2·2^1+ ...

  9. 【数位dp入门】【HDU4734】F(x)

    记录减的状态,表示还要凑多少才能达到当前值. 然后进行枚举即可.注意状态数不能重复. #include<bits/stdc++.h> #define N 10010 using names ...

随机推荐

  1. Dubbo学习系列之六(微服务架构实战)

    看了最近文章的反馈,似乎波澜不惊的样子,应该是看官觉得都是小菜,那我就直上硬菜,人狠话不多,开始!准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7 ...

  2. Java每日一面(Part2数据库)[19/11/28]

    作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 1.如何设计一个关系型数据库 如上图,首先划分成两大部分: ​ 1.存储部分:类似一个文件系统,把数据存储到一个持久化设备中,如机械硬盘,固态等 ​ ...

  3. axios统一接口管理及优化

    之前我写了一篇文章,分享了自己的项目中对于接口管理的方法.总结下来就是:定义接口文件--withAxios导出--调用接口方法.这样实现了接口的统一管理和调用接口的语义化与简单化. 根据在项目的使用, ...

  4. Sunset: Vulnhub Walkthrough

    主机扫描: ╰─ nmap -p1-65535 -sV -A 10.10.202.147 PORT STATE SERVICE VERSION21/tcp open ftp pyftpdlib 1.5 ...

  5. AWS SNS 创建 订阅 发布

    AWS SNS 创建 订阅 发布 20180810 chenxin 为实现短信报警,添加以下SNS的短信(SMS)订阅 选择主题,创建新主题,或修改原有主题 进入对应主题后,选择创建订阅,选择SMS, ...

  6. CAS服务端数据源设置

    2.CAS服务端数据源设置 2.1需求分析 我们现在让用户名密码从我们的品优购的user表里做验证 2.2配置数据源 (1)修改cas服务端中web-inf下deployerConfigContext ...

  7. 逻辑卷管理器LVM

    逻辑卷管理器LVM •将设备指定为物理卷 • 用一个或者多个物理卷来创建一个卷组 • 物理卷是用固定大小的物理区域(Physical Extent,PE)来定义的 • 在物理卷上创建的逻辑卷是由物理区 ...

  8. 你真的理解Java 注解吗?

    你真的理解Java 注解吗? 1.什么是注解? 官方解释: Java 注解用于为 Java 代码提供元数据.作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的.Java ...

  9. PanDownload

    百度盘下载地址:下载速度很快(链接)

  10. 《工作笔记:移动web页面前端开发总结》

    工作笔记:移动web页面前端开发总结 移动web在当今的发展速度是一日千里,作为移动领域的门外汉,在这段时间的接触后,发现前端开发这一块做一个小小的总结. 1.四大浏览器内核 1.Trident (I ...