对一个由(,),[,]括号组成的字符串,求出其中最长的括号匹配子串。具体来说,满足如下条件的字符串成为括号匹配的字符串:
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; } //()()([]()]][()(())])