http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4
How can anagrams result from sequences of stack operations? There are two sequences of stack operators which can convert TROT to TORT:
[ i i i i o o o o i o i i o o i o ]
where i stands for Push and o stands for Pop. Your program should, given pairs of words produce sequences of stack operations which convert the first word to the second.
Input
The input will consist of several lines of input. The first line of each pair of input lines is to be considered as a source word (which does not include the end-of-line character). The second line (again, not including the end-of-line character) of each pair is a target word. The end of input is marked by end of file.
Output
For each input pair, your program should produce a sorted list of valid sequences of i and o which produce the target word from the source word. Each list should be delimited by
[ ]
and the sequences should be printed in "dictionary order". Within each sequence, each i and o is followed by a single space and each sequence is terminated by a new line.
Process
A stack is a data storage and retrieval structure permitting two operations:
Push - to insert an item and
Pop - to retrieve the most recently pushed item
We will use the symbol i (in) for push and o (out) for pop operations for an initially empty stack of characters. Given an input word, some sequences of push and pop operations are valid in that every character of the word is both pushed and popped, and furthermore, no attempt is ever made to pop the empty stack. For example, if the word FOO is input, then the sequence:
i i o i o o | is valid, but |
i i o | is not (it's too short), neither is |
i i o o o i | (there's an illegal pop of an empty stack) |
Valid sequences yield rearrangements of the letters in an input word. For example, the input word FOO and the sequence i i o i o o produce the anagram OOF. So also would the sequence i i i o o o. You are to write a program to input pairs of words and output all the valid sequences of i and o which will produce the second member of each pair from the first.
Sample Input
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 ]
题目大意:给两个单词序列,对一个单词做入栈出栈操作,若最终可以得到第二个单词序列,那么输出操作的步骤。i代表入栈,o代表出栈。请输出所有可以得到第二个单词序列的操作且优先进行入栈操作。
思路:虽说用了堆栈的知识,但是主要还是dfs+回溯,我们用n代表单词序列的长度,用i、j作为dfs的参数,i表示当前要处理的第一个单词序列的字母下标,j表示当前要匹配的第二个单词序列的字母下标,既然要优先考虑入栈操作,那么当i<n时,我们进行入栈操作继续dfs下去;(注意回溯 要把原来改的变量修改回来)当栈非空且栈顶字母等于当前要匹配的字母时,做出栈操作继续dfs下去。dfs边界时i=j且i=n,这时候输出操作的步骤即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
int n;
string s1,s2;
int flag[1005];//1进栈 2出栈
int vis[205];
int k=0;
stack<char> s;
void dfs(int i,int j)
{
if(i==n&&j==n)//递归边界
{
for(int i=0;i<k;i++)
{
if(flag[i]==2)
printf("o ");
else
printf("i ");
}
printf("\n");
return ;
}
if(i<n)//优先进栈
{
flag[k++]=1;
s.push(s1[i]);
dfs(i+1,j);
--k; //修改信息
s.pop();
}
if(!s.empty()&&s.top()==s2[j])//考虑出栈的情况
{
char temp=s.top();
s.pop();
flag[k++]=2;
dfs(i,j+1);
s.push(temp); //修改信息
--k;
}
}
int main()
{
while(cin>>s1>>s2)
{
int flag=0;
n=s1.size();
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
vis[s1[i]]=1;
for(int i=0;i<n;i++)
{
if(!vis[s2[i]])
{
flag=1;
break;
}
}
printf("[\n");
if(!flag)
dfs(0,0);
printf("]\n");
}
}