题意:给你一个只由0和1组成的字符串,求能分成多少个由0开头0结尾并且中间01交替排列的子序列。这里题意需要注意的是,如果原字符串中由1开头或由1结尾是不合法的,如果有两个1挨着也是不合法的。
题解:由于要求输出的是每个子序列的长度以及其中数字在原字符串的位置,所以可以考虑用vector的二维数组储存分成的每个序列的元素的下标,每个一维的大小就是序列的长度。要分成的序列一定是0开头0结尾并且01交替的序列或者是只有0组成的,所以我们从左开始遍历,遇到0就存进新的容器,遇到1就存进上一个0存进的位置,并且由于每个1后面还需要一个0,所以存进1的时候我们要把标记数组下标的变量减1,使下一个出现的0存进当前这个1所在的容器。最后遍历输出就行了。
附上代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=200010;
char s[maxn];
vector<int>q[maxn];
int main()
{
scanf("%s",s); //从1开始方便记录
int len=strlen(s);
int cnt=0,num=0;
for(int i=0; i<len; i++)
{
if(s[i]=='0')
q[++num].push_back(i+1);//遇到0就放到一个新的容器里面
else
{
if(num==0) //前面没有0的子序列
{
printf("-1\n");
return 0;
}
q[num--].push_back(i+1); //出现了1就把它放在上一个0的容器里面
//并且编号要减1使下一个0也存进这个1的容器
}
cnt=max(cnt,num);
}
if(cnt!=num) //最后的不是0
{
printf("-1\n");
return 0;
}
printf("%d\n",cnt);
for(int i=1; i<=cnt; i++)
{
printf("%d ",q[i].size());
for(int j=0; j<q[i].size(); j++)
printf("%d ",q[i][j]);
printf("\n");
}
return 0;
}