• P1944 最长括号匹配(DP/贪心/括号匹配)


    题目描述

    对一个由(,),[,]括号组成的字符串,求出其中最长的括号匹配子串。具体来说,满足如下条件的字符串成为括号匹配的字符串:

    1.(),[]是括号匹配的字符串。

    2.若A是括号匹配的串,则(A),[A]是括号匹配的字符串。

    3.若A,B是括号匹配的字符串,则AB也是括号匹配的字符串。

    例如:(),[],([]),()()都是括号匹配的字符串,而][,[(])则不是。

    字符串A的子串是指由A中连续若干个字符组成的字符串。

    例如,A,B,C,ABC,CAB,ABCABCd都是ABCABC的子串。空串是任何字符串的子串。

    输入格式

    输入一行,为一个仅由()[]组成的非空字符串。

    输出格式

    输出也仅有一行,为最长的括号匹配子串。若有相同长度的子串,输出位置靠前的子串。

    输入输出样例

    输入 #1复制

    ([(][()]]()
    

    输出 #1复制

    [()]
    

    输入 #2复制

    ())[]
    

    输出 #2复制

    ()

    说明/提示

    【数据范围】

    对20%的数据,字符串长度<=100.

    对50%的数据,字符串长度<=10000.

    对100%的数据,字符串长度<=1000000

    感觉和dp没有什么关系。设id[i]表示以s[i]结尾的括号串的最长长度,当id[i - 1]存在的时候需要判断s[i - id[i - 1] - 1]是否能够和s[i]匹配,若能则令id[i] = id[i - 1] + 2;此时如果id[i - id[i]]存在的话说明可以两个括号串拼起来,则id[i] += id[i - id[i]];同时更新mxlen。当id[i - 1]不存在的时候先判断s[i - 1]能否和s[i]匹配,若能则令id[i] = 2。此时需要继续判断id[i - 2]是否存在,如果存在说明仍然可以两个括号串拼成一个大的扩号串,则令id[i] += id[i - 2];mxlen = max(mxlen, id[i]);

    注意对于()()()这样的是没有问题的因为id[3]在更新完后已经等于4了,此时就能顺利的更新id[5]了。

    #include <iostream>
    using namespace std;
    string s;
    int mxlen, id[1000005];
    int main(){
    	cin >> s;
    	for(int i = 0; i < s.size(); i++) {
    		if(i == 0) continue;
    		else if(i == 1) {
    			if(s[0] == '(' && s[1] == ')' || s[0] == '[' && s[1] == ']') id[1] = 2;
    			mxlen = max(mxlen, id[1]);
    		} else {
    			if(id[i - 1]) {
    				if(s[i - id[i - 1] - 1] == '(' && s[i] == ')' || s[i - id[i - 1] - 1] == '[' && s[i] == ']') {
    					id[i] = id[i - 1] + 2;
    					mxlen = max(mxlen, id[i]);
    				}
    				if(id[i] && id[i - id[i]]) {
    					id[i] += id[i - id[i]];
    					mxlen = max(mxlen, id[i]);
    				}
    			} else {
    				if(s[i - 1] == '(' && s[i] == ')' || s[i - 1] == '[' && s[i] == ']') id[i] = 2;
    				mxlen = max(mxlen, id[i]);
    				if(id[i] == 2 && id[i - 2]) {
    					id[i] += id[i - 2];
    					mxlen = max(mxlen, id[i]);
    				}
    			}
    		}
    	}
    	for(int i = 0; i < s.size(); i++) {
    		if(id[i] == mxlen) {
    			for(int j = i - mxlen + 1; j <= i; j++) cout << s[j];
    			break;
    		}
    	}
    	return 0;
    } 
    //()()([]()]][()(())])
    
  • 相关阅读:
    POJ3889Fractal Streets
    POJ3263 Tallest Cow
    tyvjP1288 飘飘乎居士取能量块
    洛谷P3369 【模板】普通平衡树(Treap/SBT)
    洛谷P1063 能量项链 [2006NOIP提高组]
    洛谷P1541 乌龟棋 [2010NOIP提高组]
    POJ3322 Bloxorz I
    BZOJ1218:[HNOI2003]激光炸弹
    TyvjP1266 费解的开关
    洛谷P3070 [USACO13JAN]岛游记Island Travels
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14696333.html
Copyright © 2020-2023  润新知