poj 1141 dp(补成最短的规范字符串)
来源:互联网 发布:nba球员鞋垫有数据 编辑:程序博客网 时间:2024/06/06 16:53
题意:给定一个由'(' , ')' , '[' , ']'四个字符组成的字符串s,求一个最短的合乎括号规范的字符串t,使得s是t的子序列。合乎规范的串的定义是:1. 空串。 2. 若S合乎规范, 那么(S) 和[S] 都合乎规范。3. 如果A 和 B 都合乎规范,那么AB 合乎规范。
Sample Input
([(]
Sample Output
()[()]
思路:
采用动态规划的思想。用二维数组dp[i][j]表示s[i...j]这个串变为规范的需要增加的最少字符数量。对于一个串s[l,r],分类找到子问题:
1、如果s[l]==s[r],那么dp[i][j] = dp[i+1][j-1];
2、遍历[l,r]的分割点k,求出dp[l,k]+dp[k+1][r],找到这些(包括1里面)中最小的作为dp[i][j]。
终止条件:当l==r时,只能单独匹配这一个字符。
用一个数组f记录dp[i][j]取得最小值时的动作。f数组的含义:
-1:单独匹配
-2:两边匹配
非负数:中间匹配点
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <cstdlib>using namespace std;#define clc(s,t) memset(s,t,sizeof(s))#define INF 0x3fffffff#define N 105char s[N],res[N<<1];int dp[N][N],f[N][N],len;/*f数组的含义 -1:最左边单匹配 -2:两边匹配 非负数:中间匹配点*/int match(char a,int b){ //判断a和b是否为一对匹配的括号 return (a=='('&&b==')')||(a=='['&&b==']');}int solve(int l,int r){ //记忆化dp int tmp; if(l>r) return 0; if( dp[l][r] != -1) return dp[l][r]; if(l == r){ //单独字符,只能增加一个相称字符予以匹配 f[l][r] = -1; return dp[l][r] = 1; } dp[l][r] = INF; if(match(s[l],s[r])){ //如果两边的能够匹配 tmp = solve(l+1, r-1); if(tmp<dp[l][r]){ f[l][r] = -2; dp[l][r] = tmp; } } for(int i = l;i<r;i++){ //遍历中间分隔点 tmp = solve(l, i)+solve(i+1, r); if(tmp < dp[l][r]){ dp[l][r] = tmp; f[l][r] = i; } } return dp[l][r];}char ano(char x){ //返回与输入括号相称的另一半 if(x=='(') return ')'; if(x=='[') return ']'; if(x==')') return '('; return '[';}void print(int x,int y,int l,int r){//在结果串res[x...y]中输出与原来串s[l...r]对应的部分 if(l>r || x>y) return; if(f[l][r] == -1){ //单独匹配 if(s[l] == '(' || s[l] == '['){ res[x] = s[l]; res[x+1] = ano(s[l]); }else{ res[x] = ano(s[l]); res[x+1] = s[l]; } print(x+2, y, l+1, r); }else if(f[l][r] == -2){ //两边匹配 res[x] = s[l]; res[y] = s[r]; print(x+1, y-1, l+1,r-1); }else{ //中间隔开 print(x, x+dp[l][f[l][r]]+f[l][r]-l, l, f[l][r]); print(x+dp[l][f[l][r]]+f[l][r]-l+1, y, f[l][r]+1, r); }}int main(){ int j; clc(dp, -1); clc(f, 0); scanf("%s",s); len = (int)strlen(s); j = solve(0,len-1); print(0,len-1+j,0,len-1); res[len+j] = '\0'; printf("%s\n",res);}
0 0
- poj 1141 dp(补成最短的规范字符串)
- poj 2194(字符串的DP)
- poj 1187 陨石的秘密(字符串DP)
- poj 2138 字符串dp
- poj 1159 Palindrome dp 字符串
- POJ-2192 Zipper-DP-字符串
- poj 3267 字符串dp(倒着DP)
- 区间dp(POJ - 1141)
- POJ 3267-The Cow Lexicon(DP处理字符串)
- POJ 1080 Human Gene Functions(字符串匹配得分,dp)
- POJ 1187-陨石的秘密(DP)
- POJ 1320 Ones(普通的DP)
- POJ的DP题
- poj 3280 Cheapest Palindrome(回文字符串dp)
- 日期格式化字符串的规范
- POJ 1141 Brackets Sequence(区间DP)
- POJ 1141 Brackets Sequence (区间DP)
- poj 1141 Brackets Sequence(区间dp)
- memcached学习一
- 求职最受欢迎的十大技能
- [leetcode][deque] Sliding Window Maximum
- Mahone的CTS研究笔记(四):CTS的测试内容概况(下)
- webService-WSDL文件的修改
- poj 1141 dp(补成最短的规范字符串)
- SQL Server游标的使用【转】
- Javascript、Jquery获取浏览器和屏幕各种高度宽度
- bootstrap-editable文档
- ubuntu 12.04下搭建web服务器(MySQL+PHP+Apache) 教程
- Server 层及整个MySQL体系图
- App工程结构搭建:几种常见Android代码架构分析
- TF-IDF与余弦相似性的应用(二):找出相似文章
- 畅通工程续