网易2017秋招笔试题3:最长公共子括号序列长度

【问题来源】网传的2017网易秋招笔试题

【问题描述】

【算法思路】

 下面的解题思路摘自  http://www.cnblogs.com/Atanisi/p/7500186.html

刚看到题我就想到暴力解,深搜出所有合法的括号序列,再依次比较公共子序列的长度,返回最长的。但是深搜一般和路径有关,这道题仅仅需要最大公共子序列的长度。而我们发现最大公共子序列的长度就是 s.size() - 1(当且仅当修改距离为 1 时 LCS 最大), 那么我们就想到,可以变换 s 中一个括号的位置,枚举所有的最大公共子序列长度的序列,只是需要判断是否合法。注意到,深搜是枚举所有合法的相同长度的序列,然后我们再在这个集合中去最长的。而后一种思路是我们枚举所有最长公共子序列的序列,然后再在这个集合中去掉非法的和重复的。

因为是 s, t 长度相同,并且 t 也是合法的括号序列,所以正反括号数跟原来一样。考虑在原序列上枚举一个字符,把这个插入依次到序列的某个位置去,其他序列相对顺序不变,,这样就可以让LCS最大,然后我们判断一下是否合法(这里有个小技巧),去重就用 set。

【代码】

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 int main() {
 6     string s;
 7     cin >> s;
 8     set<string> m;
 9     int n = s.size();
10     for (int i = 0; i < n; ++i) {
11         string w = s.substr(0, i) + s.substr(i + 1);
12         for (int j = 0; j < n - 1; ++j) {
13             string tmp = w.substr(0, j) + s[i] + w.substr(j);
14             int num = 0;
15             for (int k = 0; k < n; ++k) {
16                 num += (tmp[k] == '(' ? 1 : -1);
17                 if (num < 0)
18                     break;
19             }
20             if (num >= 0)
21                 m.insert(tmp);
22         }
23     }
24     cout << (int)m.size() - 1 << endl;
25 
26     return 0;
27 }
原文地址:https://www.cnblogs.com/JesusAlone/p/7536149.html