西工大NOJ字母转换

描述:

通过栈交换字母顺序。给定两个字符串,要求所有的进栈和出栈序列(i表示进栈,o表示出栈),使得字符串2在求得的进出栈序列的操作下,变成字符串1。输出结果需满足字典序。例如TROT 到 TORT:
[
i i i i o o o o
i o i i o o i o
]

输入:

给定两个字符串,第一个字符串是源字符串,第二个字符是目标目标字符串。

输出:

所有的进栈和出栈序列,输出结果需满足字典序

输入样例:

madam
adamm
bahama
bahama
long
short
eric
rice

输出样例:

[
i i i i o o o i o o
i i i i o o o o i o
i i o i o i o i o o
i i o i o i o o i o
]
[
i o i i i o o i i o o o
i o i i i o o o i o i o
i o i o i o i i i o o o
i o i o i o i o i o i o
]
[
]
[
i i o i o i o o
]

思路:

本题是一个dfs类型的练习题。对于每一个状态,只有入栈和出栈两种,所以,只需要模拟每一个状态。类似走迷宫那种题,需要模拟上下左右四个方向,这里我们只需要模拟两个方向即可。
对应于迷宫问题里面的边界问题,这里也有一些情况需要判断。
例如,当栈空的时候,就不可以进行出栈操作;当前栈顶的元素并不是我们想要的那个字符,所以也无需出栈。
栈满的情况下,也就是源字符串已经搜索完了,没有元素可以入栈了,那么,接下来的进栈操作都可以舍弃掉。
做到这些后,就可以找到所有有效的转变路径。

源代码

#include<iostream>
#include<string>
#include<stack>
#include<vector>
using namespace std;
string path[100005];
stack<char> st;
string choice = "io";//模拟所有选择,在一个位置上,要么出栈,要么进栈 

void dfs(string a, string b, int c, int k, int l){
	//查找目标串的第k个字符,源串即将处理第c个字符,在结果中放置第l个选择 
	//在所有有效的结果中,记a的长度为n,进栈n次,出栈n次。 
	if(l == 2 * a.size()){ 
		for(int i=0;i<l-1;i++){
			cout << path[i] << " ";//行尾没有多余空格 
		}
		cout << path[l-1] << endl;
	}
	else{
		//只有两个选择要么进栈,要么出栈
		for(int i=0;i<2;i++){
			path[l] = choice[i];//因为第2个选择,可以直接把第一个选择给覆盖掉,所以这里就不用回溯了
								//如果用vector存储,还需要pop_back() 
			if(i==0){//入栈 
				if(c == a.size()) //这里说明,a的元素已经全部入栈,所以接下来的i操作,全部舍弃 
					continue;
				st.push(a[c]);//入栈 
				dfs(a, b, c+1, k, l+1);//入栈的话,就要处理源串的下一个字符,没有匹配到目标串的字符,所以目标串不变,存储结果的要加1 
				st.pop();//回溯 
			}
			else{//出栈 
				if(st.empty()) continue;//栈空的话,无法出栈,所以o操作舍弃 
				char t = st.top();//保存栈顶,为了回溯 
				if(t == b[k]){//只有当前栈顶元素,等于目标串要匹配的字符,才出栈。 
					st.pop();//出栈 
					dfs(a, b, c, k+1, l+1);//出栈的话,源串不变,目标串匹配下一个 
					st.push(t);//回溯 
				}
			}
		}
	} 
}

int main(){
	string a, b;
	while(cin >> a >> b){
		cout << "[" << endl;
		//长度不等,直接跳过 
		if(a.size()!=b.size())
			continue;
		dfs(a, b, 0, 0, 0);
		cout << "]" << endl;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值