西工大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;
}
}
标签:出栈,入栈,NOJ,int,字母,西工大,st,字符串,进栈 来源: https://blog.csdn.net/qq_39884673/article/details/120615073