01子序列问题
问题描述
给定 n 个二进制字符串,要求调整字符串顺序并连接所有的字符串,使最后得到的字符串中有尽可能多的“01”子序列。输出“01”子序列的最大个数。 (1 ≤ n ≤ 100000)。
解题思路与算法思想
我们先将字串分成四类
开头是0结尾是1记为01
同理
四类字符串
01
00
11
10
之后我们会发现只有10这种字符串是可以连续连接的,因为可以保证最前面是0,
我放上了10之后在前端形成了一个01字符串并且在后面又出现了一个0
而01的字符串对于形成多余的另一序列没有任何作用
00和11可以成对的拼接成为10字符串
剩下的边角料也没有什么作用
程序模型的建立
- 选择一个00作为开头
- 之后加上10和拼接而成的10
- 最后以11结尾
- 再加上边角料
数据结构的选用
- vector
- string
程序设计流程
- 存储
- 分类
- 填充
程序设计伪码算法
while(a10.size()!=0)
{
sum.push_back(a10[a10.size()-1]) ;
a10.pop_back() ;
}
//之后看0_1
int c = min(a0.size(),a11.size()) ;
for(int i = 0 ;i<c ;i++)
{
sum.push_back(a11[a11.size()-1]) ;
a11.pop_back() ;
sum.push_back(a0[a0.size()-1]) ;
a0.pop_back() ;
}
c = min(a1.size(),a00.size()) ;
for(int i = 0 ; i<c ;i++)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
sum.push_back(a1[a1.size()-1]) ;
a1.pop_back() ;
}
//合成00 11
c = min(a00.size(),a11.size()) ;
for(int i = 0 ;i<c ;i++)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
sum.push_back(a11[a11.size()-1]) ;
a11.pop_back() ;
}
源程序编码清单
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std ;
int main(void)
{
vector<string>sum ;
vector<string>a00 ;
vector<string>a11 ;
vector<string>a01 ;
vector<string>a10 ;
vector<string>a0 ;
vector<string>a1 ;
int n ;
scanf("%d",&n) ;
for(int i = 0 ; i<n ;i++)
{
string tem ;
cin>>tem ;
if(tem.size()==1)
{
if(tem[0]== '0')
{
a0.push_back(tem) ;
//cout<<"dsakd;salkdls;kdl;askdl;ksal;dka;s"<<endl;
}
if(tem[0] =='1')
{
a1.push_back(tem) ;
}
}
else
{
//cout<<"int lese"<<endl ;
// cout<<"akjksa"<<*tem.begin()<<endl ;
// cout<<"askdjkks"<<tem[tem.size()-1]<<endl ;
if((tem[0]=='0')&&(tem[tem.size()-1]=='1'))
{
a01.push_back(tem) ;
}
if((tem[0]=='1')&&(tem[tem.size()-1]=='1'))
{
a11.push_back(tem) ;
}
if((tem[0]=='0')&&(tem[tem.size()-1]=='0'))
{
a00.push_back(tem) ;
}
if((tem[0]=='1')&&(tem[tem.size()-1]=='0'))
{
a10.push_back(tem) ;
//cout<<"here !"<<endl ;
}
}
}
//cout<<"sdkaldj"<<endl ;
//先看开头,如果都没有那也没有办法
if(a00.size()!=0)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
}
else
{
if(a0.size()!=0)
{
sum.push_back(a0[a0.size()-1]) ;
a0.pop_back() ;
}
}
//内部
//先将1——0放进去
while(a10.size()!=0)
{
sum.push_back(a10[a10.size()-1]) ;
a10.pop_back() ;
}
//之后看0_1
int c = min(a0.size(),a11.size()) ;
for(int i = 0 ;i<c ;i++)
{
sum.push_back(a11[a11.size()-1]) ;
a11.pop_back() ;
sum.push_back(a0[a0.size()-1]) ;
a0.pop_back() ;
}
c = min(a1.size(),a00.size()) ;
for(int i = 0 ; i<c ;i++)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
sum.push_back(a1[a1.size()-1]) ;
a1.pop_back() ;
}
//合成00 11
c = min(a00.size(),a11.size()) ;
for(int i = 0 ;i<c ;i++)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
sum.push_back(a11[a11.size()-1]) ;
a11.pop_back() ;
}
//加上边角料
while(a0.size()!=0)
{
sum.push_back(a0[a0.size()-1]) ;
a0.pop_back() ;
}
while(a1.size()!=0)
{
sum.push_back(a1[a1.size()-1]) ;
a1.pop_back() ;
}
while(a11.size()!=0)
{
sum.push_back(a11[a11.size()-1]) ;
a11.pop_back() ;
}
while(a10.size()!=0)
{
sum.push_back(a10[a10.size()-1]) ;
a10.pop_back() ;
}
while(a01.size()!=0)
{
sum.push_back(a01[a01.size()-1]) ;
a01.pop_back() ;
}
while(a00.size()!=0)
{
sum.push_back(a00[a00.size()-1]) ;
a00.pop_back() ;
}
// cout<<"sdkaldj"<<endl ;
string sum1 ;
string temc ;
temc.push_back(0) ;
temc.push_back(1) ;
int cnt = 0 ;
//数出来个数
//cout<<sum.size() ;
for(int i = 0 ; i <sum.size() ;i++)
{
//cout<<sum[i]<<endl ;
}
for(int i = 0 ;i<sum.size() ;i++)
{
sum1+=sum[i] ;
}
cout<<sum1<<endl ;
// cout<<"sdkaldj"<<endl ;
for(int i = 0 ;i<sum1.size() ;i++)
{
if(sum1[i]=='0'&&sum1[i+1]=='1')
{
cnt++ ;
}
}
printf("%d\n",cnt) ;
}
程序输入、输出
输入:
3
00
11
01
输出
001011
2
输入输出文件或程序运行结果截图
时间与空间复杂度分析
空间复杂度:
n^2
程序使用说明
总结与完善