题意:输入一个长度为n的01字符串s,问最少能分成几个010101....或101010....的子序列,并输出每个字符属于第几个子序列。
思路:总共就是四种情况0,1,010101....,101010...,如果当前字符是1,我们就看之前是否存在一个以0结尾子序列,有就接上去,没有则说明又要多分一个,同理当当前字符是0。所以我们可以用队列来做,循环扫描一遍是否有与当前字符相反的末尾字符的子序列即可,如果有说明当前字符可以接到当前子序列中,我们按照题意用数组a来储存。
代码:
#include <set>
#include <map>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
 
 
using namespace std;
const int INF = 0x3f3f3f3f;//?????
typedef long long ll;
typedef long double ld;
typedef pair<ll, int>  pll;
typedef pair<int, int> pii; 
const int N = 1000000;
int a[200005],b[105],prime[N],st[N];ll sum[N];
int cnt;
ll qpow(ll x,ll y,ll mod)
{
	int ans=1;
	while(y)
	{
		if(y&1) ans=ans*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ans%mod;
}
void ola()
{
	for(int i=2;i<=1000000;i++)
	{
		if(st[i]==0)
		{
			prime[cnt++]=i;
		}
		for(int j=0;j<cnt&&i*prime[j]<=1000000;j++)
		{
			st[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		 } 
	}
}
int main()
{
	IOS;
	int t; cin >> t;
	while(t--)
	{
		int n; cin >> n;
		string s; cin >> s;
		queue<int> q1,q2;
		int k=0;
		for(int i=0;i<n;i++)
		{
			if(s[i]=='0')
			{
				if(q2.size()!=0)
				{
					int tmp=q2.front();
					q2.pop();
					a[i]=a[tmp];
					q1.push(i);
				}
				else 
				{
					a[i]=++k;
					q1.push(i);
				}
			}
			else 
			{
				if(q1.size()!=0)
				{
					int tmp=q1.front();
					q1.pop();
					a[i]=a[tmp];
					q2.push(i);
				}
				
				else 
				{
					a[i]=++k;
					q2.push(i);
				}
			}
		}
		cout << k << endl;
		for(int i=0;i<n;i++)
		cout << a[i] << " ";
		cout << endl;
	}
	return 0; 
}