算法题目——最长公共子括号序列

链接:https://www.nowcoder.com/questionTerminal/504ad6420b314e5bb614e1684ad46d4d
来源:牛客网

一个合法的括号匹配序列被定义为:
1. 空串""是合法的括号序列
2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列
3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列
4. 每个合法的括号序列都可以由上面的规则生成
例如"", "()", "()()()", "(()())", "(((()))"都是合法的。
从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
例如"abcde"的子序列有"abe","","abcde"等。
定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t:
1、t跟s不同,但是长度相同
2、t也是一个合法的括号匹配序列
3、LCS(s, t)是满足上述两个条件的t中最大的
因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。

如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有:
"()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3.

输入描述:

输入包括字符串s(4 ≤ |s| ≤ 50,|s|表示字符串长度),保证s是一个合法的括号匹配序列。

输出描述:

输出一个正整数,满足条件的t的个数。

示例1

输入

(())()

输出

3

分析

题目要求对所有的相同长度的括号序列进行遍历,并计算每一个括号序列与题目中给定的字符串的最长公共子序列的长度。然后,计算长度最大的值出现了多少次。

如果真的按照题目的描述去做,显然是不可能做出来的。光是生成长达50个字符串的括号序列可能花的时间就超了。

既然要搜索最长的出现了多少次,不如假设出现了最长的子串是原串长度-1,然后求所有由这个子串所构成的括号序列。如果不存在,则求子串长是原串长度-2的串所能构成的括号序列。依次递减这个子串的长度,直到能求出来为止。

其实,一定存在子串长度为原串长度-1的串通过添加新的括号所构成的另一个和原串不同的括号序列。这是因为,任何一个括号序列都可以只移动一个括号构成另外一个和原来不同的括号序列(思考为什么)。如果可以这样,那么新串和原串的最长公共括号子序列就是n-1个。因为你只移动了一个括号并插入到其他地方。那么除了这个括号外,其他的顺序都没有变。那么,每次将其中一个括号拿掉,然后插入到新的地方。我们统计一下总共能构成多少个合法的括号序列,将这个数字减去原来的那个串,也就是减去1,就是题目的答案。

#include 
#include 
#include 
#include 

using namespace std;

bool isKuohao(const string & str)
{
    int count=0;
    for(auto c:str)
    {
        if(c == '(')
            count ++;
        if(c == ')')
            count --;
        if(count<0)
            return false;
    }
    return count == 0;
}

int main()
{
    int ret=0;
    string input;
    cin >> input;
    set haveChose;
    set haveBuild;
    /* 选出其中任意一个括号 */
    for (int i = 0; i < input.size(); i++)
    {
        char q[] = {input[i], '\0'};
        /* 删除该括号 */
        string delete_char(input);
        delete_char.erase(delete_char.begin() + i);
        if (haveChose.count(delete_char))
            continue;
        else
            haveChose.insert(delete_char);
        /* 将原来的括号插入新的数组中 */
        for (int j = 0; j < delete_char.size() + 1; j++)
        {
            string add_delete_char(delete_char);
            add_delete_char.insert(j, q);
            if (haveBuild.count(add_delete_char))
                continue;
            else
                haveBuild.insert(add_delete_char);
            if(isKuohao(add_delete_char)){
                ret ++;
            }
        }
    }
    cout << ret-1 << endl;
}

你可能感兴趣的:(算法题目——最长公共子括号序列)