拿到这个题第一时间我是懵逼的,最终也没做出来,不过后来继续思考,又找了找资料,思路就出来了。
首先是找到合法的括号序列。(这也是我的瓶颈,之前没接触过这种题,哎,太low了我。)
此处参考博客:http://blog.youkuaiyun.com/xiaohei00000/article/details/50859678
分析:
给定数组n,求n对括号可以组成的括号序列。
因为数字为n,所以每个字符串长度为2n,根据括号规则我们可以知道,在第1到第2n的任一个位置都满足:左括号的个数大于等于右括号的个数。
所以,在位置k还剩余left个左括号和right个右括号
如果left>0,则可以打印左括号;
而right必须小于等于left,right<=left,否则不能打印右括号。
当right==0 && left==0的时候,说明有了一个合法的序列,可以将其存储起来。
第二,用动态规划方法求最长公共子序列。
参考博客:http://blog.chinaunix.net/uid-26548237-id-3374211.html
然后就没什么好介绍的了,代码上面都有,应该很好懂。
import java.util.Scanner;
import java.util.Vector;
/** * Created by gentl on 2017/9/11. */
public class T2 {
/*求出和已知字符串长度相同的合法字符串 此处参考http://blog.youkuaiyun.com/xiaohei00000/article/details/50859678 */
Vector<String> restore = new Vector<>();
// 声明数组,用来存放所有合法字符串
Vector<String> generateParenthesis(final int n) {
if (n <= 0) {
return this.restore;
}
generateParenthesisHelper(n, n, "");
return this.restore;
}
// 递归构造合法的括号序列
void generateParenthesisHelper(final int left, final int right, final String str) {
if (right == 0) {
this.restore.add(str);
} else {
if (left > 0) {
generateParenthesisHelper(left - 1, right, str + "(");
}
if (right > left) {
generateParenthesisHelper(left, right - 1, str + ")");
}
}
}
// 用动态规划方法求最大的公共子序列的长度
static int lcsequence(final String str1, final String str2) {
final int len1 = str1.length();
final int len2 = str2.length();
final int[][] c = new int[len1 + 1][len2 + 1];
for (int row = 0; row <= len1; row++) {
c[row][0] = 0;
}
for (int column = 0; column <= len2; column++) {
c[0][column] = 0;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
c[i][j] = c[i - 1][j - 1] + 1;
} else {
c[i][j] = c[i][j - 1] > c[i - 1][j] ? c[i][j - 1] : c[i - 1][j];
}
}
}
return c[len1][len2];
}
public static void main(final String[] args) {
final Scanner in = new Scanner(System.in);
final String str = in.next();
final int len = str.length();
final int num = len / 2;
final T2 t2 = new T2();
final Vector<String> vs = t2.generateParenthesis(num);
final int count = vs.size();
final int[] countLcs = new int[count];
int maxLcsLength = 0;
for (int i = 0; i < count; i++) {
if (vs.elementAt(i).equals(str)) {
countLcs[i] = 0;
} else {
countLcs[i] = lcsequence(vs.elementAt(i), str);
if (countLcs[i] > maxLcsLength) {
maxLcsLength = countLcs[i];
}
}
}
int simStrNum = 0;
for (int i = 0; i < count; i++) {
if (countLcs[i] == maxLcsLength) {
simStrNum++;
System.out.println(vs.elementAt(i));
}
}
System.out.println("最大公共子序列长度为:" + maxLcsLength + "\n" + "共有" + simStrNum + "个字符串符合要求。");
}
}