第二题

我在做的时候大体知道怎么做,但就是不会模拟,不知道代码具体怎么写的,看了苯环的讲解才恍然大悟。这道题是一个常见的模型:用栈来模拟括号匹配

模型:用栈进行括号匹配

主题思路就是先在一个栈里面存入一些括号,遍历一下,如果这个括号是")",并且上一个括号是"("。直接把左括号弹出(这时右括号也没有加进去),相当于匹配成功,把这个括号删除了。

利用这个思想就可以把这道题目解决了

思路

把m和o当做一组括号,ni和o当做一组括号。用string来模拟栈,这样就可以进行括号匹配的操作。

看一下代码


#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define sc scanf
#define pf printf
#define x first
#define y second

using namespace std;

typedef long long LL;
typedef unsigned long long ull;
typedef pair<int, int> PII;

int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
int ddx[] = {-1, 1, 0, 0, -1, 1, -1, 1};
int ddy[] = {0, 0, -1, 1, -1, -1, 1, 1};

LL ksm(LL a, LL b, LL p)
{
    LL sum = 1;
    a %= p;
    while (b)
    {
        if (b & 1)  sum = (sum * a) % p;
        b >>= 1;
        a = (a * a) % p;
    }
    return sum % p;
}

bool is_prime(int x)
{
	if (x == 0 || x == 1)  return false;
	for (int i = 2; i * i <= x; i ++)
		if (x % i == 0)  return false;
	
	return true;
}

bool is_runyear(int y)
{
	return (y % 400 == 0 || (y % 100 != 0 && y % 4 == 0));
}

LL gcd(LL x, LL y)
{
	while (y)
	{
		x %= y;
		swap(x, y);
	}
	return x;
}

const int N = 110;

/*
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    1 3 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    1 4 6 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    ...
*/



void solve()
{
    int n;
    string s;
    cin >> n >> s;
    string t;
    for (auto & c : s)
    {
        if (c == 'o')
        {
            if (t.size() && t.back() == 'm')
                t.pop_back();
            else 
                t += c;
        }
        else if (c == 'u')
        {
            if (t.size() >= 2 && t[t.size() - 2] == 'n' && t[t.size() - 1] == 'i')
            {
                t.pop_back();
                t.pop_back();
            }
            else
                t += c;
        }
        else
            t += c;
    }
    if (t.empty())
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}


int main()
{
	IOS;
	int _ = 1;
// 	cin >> _;
	while (_ --)
	{
		solve();
	}
	
	return 0;
}

思路解释

开了一个string s用来存题目的字符串,然后我们开一个string t,从头开始遍历s(下标从0开始)。ni和u,m和o是两组并列的“括号”。

1.先讨论mo,如果当前在s遍历的字符是o,判断t的尾部是不是m,如果是,就把m弹出,o也不加在t里面,相当于删去了mo。如果t的尾部不是m,那就把o塞进t里,这也就意味着这个o不会被削掉哦了。 2.再讨论niu,我们把ni,u分开,如果当前s遍历的字符是u,判断t的尾部和尾部前一个字符是不是i和n,如果是,把这两个字符弹出。如果不是,把u加进去。 3.如果当前s遍历的字符既不是o也不是u,就说明是“左括号n, i, m”或者其他的字符,直接塞进t里就好了。

最后判断一下:如果t是空的,就说明全部被消掉了,输出Yes,否则输出No。