题意:输入一个长度为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;
} 
京公网安备 11010502036488号