吐泡泡题解

链接:https://ac.nowcoder.com/acm/problem/15029?&headNav=acm
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

小鱼儿吐泡泡,嘟嘟嘟冒出来。小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o"。
两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。
(是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道。)
例如:ooOOoooO经过一段时间以后会变成oO。

输入描述:

数据有多组,处理到文件结束。
每组输入包含一行仅有'O'与'o'组成的字符串。

输出描述:

每组输出仅包含一行,输出一行字符串代表小鱼儿吐出的泡泡经过融合以后所剩余的泡泡。

示例1

输入

ooOOoooO

输出

oO

说明

自左到右进行合并

备注:

对于100%的数据,
字符串的长度不超过100。

算法解析:
栈思想
模拟:

ooOOoooO
t=o    o    空栈,入栈
t=o    oo->O    非空,融合,弹出o,压入O
t=O    OO->    非空,融合,弹出O
t=O    O    空栈,入栈
t=o    Oo    非空,融合,压入o
t=o    Ooo->OO->    非空,融合,弹出o,压入O,栈首与栈首后一位可融合,将栈首作为新的临时元素,再来一次play(写一个判断函数,判断栈首与栈首后一位是否可融合,若不可融合则过,否则循环)
t=o    o    空栈,入栈
t=O    oO    非空,融合,压入O
此时栈从上到下排列如下
Oo
算法结束后应该倒序输出
倒序输出方法如下:先一个一个输出至string容器中,再反转string即可
算法抽象如下:
i 若空栈,压入
ii 若非空,融合,操作,判断栈首与后一位是否可融合,是则继续融合,否则过
如果可以继续融合,那么函数参数a变为栈首元素,弹出栈首,继续操作
考虑到只有Ooo可以继续,所以可以简化算法
Ooo->OO
ooo->oO
注意:oo会空栈
获取知识点:

对于stack,pop是弹出,top是获取!
把STL传入参数用&引用

#include<cstdio>
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int fuse(char a,char b) { //融合函数,无效操作返回0,两个小的返回1,两个大的返回2
	if(a=='o' && b=='O')	return 0;
	if(a=='O' && b=='o')	return 0;
	if(a=='o' && b=='o')	return 1;
	if(a=='O' && b=='O')	return 2;
}
bool judge(stack<char> a) { //判断栈首与后一位是否可融合
	char temp;
	temp=a.top();
	a.pop();
	if(fuse(a.top(),temp))	return true;
	else return false;
}
void play(stack<char> &old,char a) { //从字符串逐次获取元素,进行如下操作
	if (old.empty()) { //i:若栈为空,压入栈
		old.push(a);
		return;
	} else { //ii:若非空,融合,操作,判断栈首与后一位是否可融合,是则继续融合,否则过
		int ans;//存放fuse的结果
		char temp=old.top();
		ans=fuse(a,temp);
		if(ans==0) {
			old.push(a);
			return;
		} else if(ans==1) {	//oo融合为O
			old.pop();
			old.push('O');
			char temp=old.top();
			old.pop();
			if(!old.empty()	&& old.top()=='O')	old.pop();
			else	old.push(temp);
		} else if(ans==2) {	//OO破碎
			old.pop();
		}
	}
	
}
string copy(stack<char> &sta) {
	string a;
	while(!sta.empty()) {
		a+=sta.top();
		sta.pop();
	}
	return a;
}
void reverseStr(string& str) //字符串反转 
{ 
	int n = str.length(); 
	for (int i = 0; i < n / 2; i++) 
		swap(str[i], str[n - i - 1]); 
} 
int main() {
	string str1;
	while(cin>>str1) {
		stack<char> old;
		for(int i=0; i<str1.length(); i++) {
			char now=str1[i];
			play(old,now);
		}
		string ans;
		ans=copy(old);
		reverseStr(ans);
		cout<<ans<<endl;
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值