题目来源
https://www.luogu.com.cn/problem/P1087
https://www.acwing.com/problem/content/description/421/
题目描述
我们可以把由“ 0 0 0”和“ 1 1 1”组成的字符串分为三类:全“ 0 0 0”串称为 B B B串,全“ 1 1 1”串称为 I I I串,既含“ 0 0 0”又含“ 1 1 1”的串则称为 F F F串。
F B I FBI FBI树是一种二叉树,它的结点类型也包括 F F F结点, B B B结点和 I I I结点三种。由一个长度为 2 N 2^N 2N的“ 01 01 01”串S可以构造出一棵 F B I FBI FBI树 T T T,递归的构造方法如下:
- T T T的根结点为 R R R,其类型与串 S S S的类型相同;
- 若串 S S S的长度大于 1 1 1,将串 S S S从中间分开,分为等长的左右子串 S 1 S_1 S1和 S 2 S_2 S2;由左子串 S 1 S_1 S1构造R的左子树 T 1 T_1 T1,由右子串 S 2 S_2 S2构造 R R R的右子树 T 2 T_2 T2。
现在给定一个长度为 2 N 2^N 2N的“ 01 01 01”串,请用上述构造方法构造出一棵 F B I FBI FBI树,并输出它的后序遍历序列。
输入格式
第一行是一个整数 N ( 0 ≤ N ≤ 10 ) N(0 \le N \le 10) N(0≤N≤10),
第二行是一个长度为 2 N 2^N 2N的“ 01 01 01”串。
输出格式
一个字符串,即 F B I FBI FBI树的后序遍历序列。
样例输入 #1
3
10001011
样例输出 #1
IBFBBBFIBFIIIFF
提示
对于40%的数据, N ≤ 2 N \le 2 N≤2;
对于全部的数据, N ≤ 10 N \le 10 N≤10。
算法代码一
算法代码一来源于:https://www.acwing.com/solution/content/5497/
#include <bits/stdc++.h>
using namespace std;
void dfs(string str) {
if(str.size()>1) {
dfs(str.substr(0,str.size()/2));
dfs(str.substr(str.size()/2));
}
int one=0, zero=0;
for(int i=0; i<str.size(); i++)
if(str[i]=='0') zero++;
else one++;
if(one && zero) cout<<'F';
else if(one) cout<<'I';
else cout<<'B';
}
int main() {
int n;
string str;
cin>>n>>str;
dfs(str);
return 0;
}
/*
in:
3
10001011
out:
IBFBBBFIBFIIIFF
*/
为了弄明白此代码,需要深入理解函数substr()的用法。如下所示。
#include <bits/stdc++.h>
using namespace std;
int main() {
string s="abcdef";
string a=s.substr(0,s.size()/2); //从下标0开始输出s.size()/2个字符
string b=s.substr(s.size()/2); //从下标s.size()/2开始输出所有字符
string c=s.substr(2,s.size()/2); //从下标2开始输出s.size()/2个字符
cout<<s.size()/2<<endl; //3
cout<<a<<" "<<b<<endl; //abc def
cout<<c<<" "<<b<<endl; //cde def
return 0;
}
当然,若此题改为要求输出中序的 F B I FBI FBI树,则代码略作调整如下:
#include <bits/stdc++.h>
using namespace std;
void dfs(string str) {
if(str.size()>1) {
dfs(str.substr(0,str.size()/2));
}
int one=0, zero=0;
for(int i=0; i<str.size(); i++)
if(str[i]=='0') zero++;
else one++;
if(one && zero) cout<<'F';
else if(one) cout<<'I';
else cout<<'B';
if(str.size()>1) {
dfs(str.substr(str.size()/2));
}
}
int main() {
int n;
string str;
cin>>n>>str;
dfs(str);
return 0;
}
/*
in:
3
10001011
out:
IFBFBBBFIFBFIII
*/
相应地,若此题改为要求输出先序的 F B I FBI FBI树,则代码略作调整如下:
#include <bits/stdc++.h>
using namespace std;
void dfs(string str) {
int one=0, zero=0;
for(int i=0; i<str.size(); i++)
if(str[i]=='0') zero++;
else one++;
if(one && zero) cout<<'F';
else if(one) cout<<'I';
else cout<<'B';
if(str.size()>1) {
dfs(str.substr(0,str.size()/2));
dfs(str.substr(str.size()/2));
}
}
int main() {
int n;
string str;
cin>>n>>str;
dfs(str);
return 0;
}
/*
in:
3
10001011
out:
FFFIBBBBFFIBIII
*/
算法代码二
#include <bits/stdc++.h>
using namespace std;
const int maxn=1050;
char s[maxn];
int n;
void create(int x,int y) {
if(y>x) {
create(x,(x+y)/2);
create((x+y+1)/2,y);
}
int B=1,I=1;
for(int i=0; i<=y-x; i++) {
if(s[x+i]=='1')
B=0;
else if(s[x+i]=='0')
I=0;
}
if(B)
cout<<'B';
else if(I)
cout<<'I';
else
cout<<'F';
}
int main() {
cin>>n>>s;
create(0,(1<<n)-1);
return 0;
}
/*
in:
3
10001011
out:
IBFBBBFIBFIIIFF
*/
参考文献
https://blog.csdn.net/weixin_44170305/article/details/109568533
https://www.acwing.com/solution/content/5497/