题意:输入一个长度为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; }