题目描述
W型串
一个由括号构成的字符串称为W型串(W-string),当且仅当该串可以表示为(A)或(A)(B)的形式,其中A,B是空串或W型串.
例如()、((()))、(())()等是W型串,而()()()、(()(())())等不是W型串. 给出n个由括号构成的非空字符串,判断每个串是否为W型串.
输入
第一行为一个正整数n,表示需判断的字符串个数. 接下来n行,每行一个仅由左右括号(ASCII码分别为40和41)构成的非空字符串S.
0 < |S| <= 1000; n <= 100.
输出
输出n行,分别对应每个字符串是否为W型串,如果是则输出Yes,否则输出No.
输入样例
8
(((((())))))
))()(
((((()
(()(()))
((()())(()()))((()())(()()))
(()(())()((())))()
((())(()))((())(()))
(((()()(((()))))))
输出样例
Yes
No
No
Yes
Yes
No
Yes
No
解题思路
W型串这个定义本来就是递归定义的,所以自然想到要递归的处理首先考虑几个基本的情况
- 如果这个串是空的,显然是W型串
- 如果这个串一开始不是(,显然不是W型串
- 如果这个串不以)结尾,显然也不是W型串
那么,我们可以借鉴括号匹配的思路,把所给的串拆成若干个括号匹配的序列然后分别判断它是不是W型串。如果括号匹配的话我们把这个串的第一个括号和最后一个括号都去掉,然后判断去掉括号的序列是不是W型串,这样一直递归下去判断即可。我这里用了substr函数取子串其实大可不必这样,可以直接在函数参数里指定起始结束位置。
AC代码
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <cstdlib>
#include <map>
#include <string>
#include <cmath>
#include <cctype>
#include <stack>
#include <queue>
#include <climits>
#include <set>
using namespace std;
int n;
bool judge(string s) {
if (s.empty()) return true;
if (s[0] != '(') return false;
if (s[s.length() - 1] != ')') return false;
if (s[0] == '('&&s[1] == ')'&&s.length()==2) return true;
stack<char> S;
while (!S.empty()) S.pop();
int i;
for ( i = 0; i < s.length(); i++) {
if (s[i] == '(') S.push(s[i]);
else S.pop();
if (S.empty()) {
if (i == s.length() - 1) i++;
break;
}
}
if (!S.empty()) return false;
if (i == s.length()) {
string tmp = s.substr(1, i - 2);
return judge(tmp);
}
else {
int ii = s.length() - 2;
string tmp = s.substr(1, i - 1);
string tmpp = s.substr(i + 2);
tmpp.erase(tmpp.length() - 1);
return(judge(tmp) && judge(tmpp));
}
}
int main() {
//freopen("Text.txt", "r", stdin);
scanf("%d", &n);
while (n--) {
string s1;
cin >> s1;
if (judge(s1)) printf("Yes\n");
else printf("No\n");
}
return 0;
}
小结
解决结构一样只是规模不一样的问题用递归最好辣