ZOJ 1004 Anagrams by Stack

dfs+回溯(严格地说不是回溯,但是作用与回溯一样)

我这个解释可能说的不是很清楚,我也明白,因为要讲的很清楚必须要很详细,要从底层思考讲起。我看了别的博主写的代码,大部分核心代码都是很长的,我这个可以说是比较短的了,核心就是那个dfs。还有就是我写的那些个位置是传参来的,用传参就是巧妙的地方!位置这些就不用回溯了。当然c语言,不想c++有那些方便的函数利用,怎么说,更加锻炼思维。当然不是说不用方便的函数,有了这些函数,并且你还用得很好这本身就是值得骄傲的事。

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 ois 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

Sample Output

[
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 
]
#include<stdio.h>
#include<string.h>
int lenth;
char s[100],at[100],io[100],st[100];    //s是原始串,at是栈,io是输出串,st是目标串
void reat(int i)    //这不好解释,我说一种情况就懂了,没当我们满足一次目标串,那么我们的at栈就为空,因为at串是全局变量,可是我们回溯是需要用到at串的,比如我们要在第三个位置回溯,可我们的栈为空了还怎么回溯?,所以我们就要按照io串第三个位置之前重新赋值,至于为什么这样,为什么能这样赋值就算是回溯就留给你们思考了,算法就是锻炼思维的。
{
    for(int c=0,k=0,j=0;j<i;j++)
    {
        if(io[j]=='i')
            at[c++]=s[k++];
        else
            c--;
    }
}
void dfs(int i,int j,int k,int m)    //i是即将入栈的位置,j是原始串的入栈位置,k是匹配目标串的位置,m是输出串的位置
{
    if(m==2*lenth)    //当m==2*lenth时输出就是正确的
    {
        for(int f=0;f<m;f++)
            printf("%c ",io[f]);
        puts("");
        return ;
    }
    for(int l=0;l<2;l++)    //每一次两种选择嘛,把这个i选择放在前面就可以避免再写字典序排序
    {
        if(l==0&&j<lenth)    //l==0好说代表第一种选择,j<lenth:每进入一次for循环都有两种选择但是当我们所有字符都进入了就不会有i选择对吧,就只有o选择。
        {
            at[i]=s[j];    //这就是入栈,可为什么要把这两个位置分开写呢?因为出栈了自然i--,可是原始串却不会j--,因为同一个字符肯定不能重复进栈
            io[m]='i';    //代表一次进栈
            dfs(i+1,j+1,k,m+1);    下一次进栈的位置就是i+1,下一个原始串字符是j+1,k是匹配的位置进栈操作是不匹配的,m+1代表下一次操作的位置
        }
        if(l==1)
        {
            reat(m);    //回溯
            if(at[i-1]==st[k])    //匹配为什么是i-1因为i是即将入栈的位置,i-1才是栈顶,k一直都是等待匹配的位置
            {
                io[m]='o';    //代表一次出栈
                dfs(i-1,j,k+1,m+1);    //即出栈了就要i-1,出栈操作无关赋值j还是j,一个位置匹配了就该下一个了呗,m+1依旧代表下一次操作的位置
            }
        }
    }
}
int main()
{
    while(~scanf("%s",s))
    {
        memset(io,0,sizeof(io));    //因为是全局变量所以要清零
        scanf("%s",st);
        lenth=strlen(s);
        at[0]=s[0];    //第一次只能进栈操作,这不用多说吧
        io[0]='i';
        puts("[");
        dfs(1,1,0,1);
        puts("]");
    }
}

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Heredy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值