网易校招编程题------最长公共子括号序列

题目描述

这里写图片描述

思路分析:

根据题意,要想使得 LCS 最大,删去任意一个字符即可获得 LCS = |s| - 1 ,再把该字符插到与原来不同的任意位置可以维持原长度,而不影响 LCS 的计算。

因此最暴力的做法是枚举每个字符,把它插入到任意位置,判合法,去重,累计。

优化 1 :插入是插到指定位置的字符之前,如果插入的字符和该位置的字符相同,则插入后还是原字符串,可以跳过这种情况。否则最后的结果要 - 1 。
优化 2 :左右两边一定是左右括号,不用移动它们。但字符却可以插到它们的后面。

判合法:实际上就是括号匹配的平衡性。在这里,如果我们从前到后遍历,左括号可以暂时多于右括号,但不可以少于,因为能够闭合右括号的左括号都在左边,这里其实可以直接通过左括号数是否小于有括号数来判别,英文开始给的序列是合法的,所以左右括号的个数一定是相等的,不用担心左括号数本来就大于右括号的情况。

实例代码:

package com.zhumq.lianxi;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class MatchKuoHao {
    //直接使用set来去重
    private static Set<String> set = new HashSet<String>();
    static int count = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        getSequence(str);
        System.out.println(set.size() - 1);
        sc.close();
    }

    private static void getSequence(String str) {
        for (int i = 0; i < str.length(); i++) {
            StringBuilder sb = new StringBuilder(str);
            char c = str.charAt(i);
            sb.deleteCharAt(i);
            for (int j = 0; j < str.length(); j++) {
                sb.insert(j, c);
                if (isLegal(sb.toString())) {
                    set.add(sb.toString());
                }
                sb.deleteCharAt(j);
            }
        }
    }

    private static boolean isLegal(String s) {
        int left = 0, right = 0;
        //由于左右括号的数目一定相同,可以直接用有括号是否多于左括号来判断是否合法
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(')
                left++;
            else
                right++;
            if (right > left)
                return false;
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/DjokerMax/article/details/81747618