Codeforces 1399D

D. Binary String To Subsequences
time limit per test2 seconds
memory limit per test256 megabytes
input standard input
output standard output
You are given a binary string s consisting of n zeros and ones.

Your task is to divide the given string into the minimum number of subsequences in such a way that each character of the string belongs to exactly one subsequence and each subsequence looks like “010101 …” or “101010 …” (i.e. the subsequence should not contain two adjacent zeros or ones).

Recall that a subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, subsequences of “1011101” are “0”, “1”, “11111”, “0111”, “101”, “1001”, but not “000”, “101010” and “11100”.

You have to answer t independent test cases.

Input

The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤2⋅105) — the length of s. The second line of the test case contains n characters ‘0’ and ‘1’ — the string s.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output

For each test case, print the answer: in the first line print one integer k (1≤k≤n) — the minimum number of subsequences you can divide the string s to. In the second line print n integers a1,a2,…,an (1≤ai≤k), where ai is the number of subsequence the i-th character of s belongs to.

If there are several answers, you can print any.

Example
input
4
4
0011
6
111111
5
10101
8
01010000
output
2
1 2 2 1
6
1 2 3 4 5 6
1
1 1 1 1 1
4
1 1 1 1 1 2 3 4

题目大意:

先输入 t 表示 t 组测试用例,每组输入一个n表示长度,然后输入长度为n
的01串,你需要将其子序列(可以不连续)分组,每组只能形如 0101… | 10101… 不能出现连续的0或1,然后需要输出分好的组数,再输出每一个字符对应的哪一组。

解题思路:

利用两个vector 存0和1的组别(代码中会有说明),0只能作为该组的开头或者跟在1后面,1亦然。拿0为例,每次判断存1的向量是否为空,如果为空则说明这个0需要做改组的首字符,令pos = (pos1.size() + pos0.size()),表示该0到了哪一组。如果不为空则删除1所在向量的末尾,并将pos1 末尾的编号存入0所在向量的尾部。

Code:

#pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 150;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		string s;
		cin >> n >> s;
		vector<int > pos0, pos1;//用于存放该 0  1所在的组别
		vector<int > ans(n);//存答案
		int i = 0;//从第1个(下标为0开始遍历)
		for (auto ch : s)
		{
			int pos = pos1.size() + pos0.size();//默认到了pos组
			if (ch == '0')//这里是最妙的,利用抵消的原理只要1里有数,那么就消除1,放在pos0,做到pos1.size() + pos0.size() 就是最终组数
			{
				if (pos1.empty())
					pos0.push_back(pos);
				else
				{
					pos = pos1.back();
					pos1.pop_back();
					pos0.push_back(pos);
				}
			}
			else
			{
				if (pos0.empty())
					pos1.push_back(pos);
				else
				{
					pos = pos0.back();
					pos0.pop_back();
					pos1.push_back(pos);
				}
			}
			ans[i++] = pos;
		}
		cout << pos0.size() + pos1.size() << endl;//最终的组别
		for (auto it : ans)  cout << it + 1 << ' ';//这里要 + 1,因为pos0 + pos1 最初都是0,但其实是从第一组开始
		cout << endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Hayasaka/p/14294155.html