AcWing 150. 括号画家

题目

算法1

括号配对通常用栈,如果发现后括号和栈顶的元素相匹配,那么将其推出。

如果所有元素都是合法(这里的合法是题目定义的),且按顺序入栈(不管是前括号还是后括号都要入栈,只有配对了才弹出),那么最后栈应该是空的;这个问题就是讨论某一括号序列是否合法。

现在给一组括号序列,需要求出最长的合法括号序列的长度。

这里的栈用二元组,第一个元素记录符号,第二记录位置。

如果当中的括号序列时不合法的,也就是乱的,那么后面来的后括号就一定不可能与前面的括号相配对。

那么我们只需要遍历字符串,遇到前括号将其推入栈,配对时弹出栈顶,并记录一次长度(用后括号的位置减去前括号的位置)。

100 pts

#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
const int N = 1e5+10;

typedef pair<char, int> PCI;
stack<PCI> s;

bool check(char &a, char &b)
{
    if(a == '(' && b == ')') return true;
    if(a == '{' && b == '}') return true;
    if(a == '[' && b == ']') return true;
    return false;
}

int main()
{
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    
    char str[N]; cin >> str + 1;
    int res = 0;
    for(int i = 1; i <= strlen(str + 1); i ++ )
    {
        if(s.size() && check(s.top().first, str[i]))
        {
            s.pop();
            if(s.size()) res = max(res, i - s.top().second);
            else res = max(res, i);
            //cout<<i<<" "<<j<<endl;
        }
        else s.push({str[i], i});
    }
    cout << res;
    return 0;
}

算法2

动态规划

都是\(O(n)\)的时间复杂度,动态规划的代码更简单一些。

我们设\(f_i\)等于\(i\)结尾的最长合法子串长度。

注意,答案需要取任意\(f_i\)的最大值,而不是\(f_n\)

分三种情况讨论:

  1. 如果读入一个前括号,不去动,等到后括号来匹配

  2. 如果读入后括号,则需要配对。我们假设算法的正确性,那么\(f_{i-1}\)一定表示以前一位结尾的最长合法序列,如下例。很明显\(f_{i-1}\)是中括号当中含两个小括号,那么此时要配对的就是前面的大括号,位置是\(i - f_{i - 1} - 1\),判断这一位置是否匹配再更新。长度加二。

           i-1
            |
[(){}]{[()()]}
             |
             i
  1. 注意,连接两个合法的序列也是合法的操作,那么需要再加上再前一位的f值。

问题迎刃而解。

100 pts

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
char s[N];
int f[N];

int main()
{
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	
	cin >> s + 1;
	int n = strlen(s + 1);
	
	int res = 0;
	for(int i = 2; i <= n; i ++ )
	{
		if(s[i] == '(' || s[i] == '{' || s[i] == '[') continue;
		
		char c = s[i - f[i - 1] - 1]; 
		if(c =='{' && s[i] == '}' || c =='[' && s[i] == ']' || c =='(' && s[i] == ')') //与之前的括号匹配 
			f[i] = f[i - 1] + 2, f[i] += f[i - f[i - 1] - 2];
		res = max(res, f[i]);
	}
	cout << res;
	
	return 0;
}
posted @ 2023-01-27 12:42  Sankano  阅读(26)  评论(0编辑  收藏  举报