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