【算法实验二】--【回溯法】--字母转换

1143.字母转换

时限:1000ms 内存限制:10000K  总时限:3000ms

描述

通过栈交换字母顺序。给定两个字符串,要求所有的进栈和出栈序列(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 i o i

o i o o

]

先解释一下这个输入和输出,输出是先输出一个大括号,然后每行一种可能性的序列,不能输出就直接输出括号。

还有很重要的一点就是,由于输入是以空格为分开的标志,所以应该用scanf比较方便。

题目解析:表示这个题好难,,根本不会,看别人的代码看了半天才看懂,然后意识到原来做法这么简单,,,好了详细说一下这个题。因为是用回溯法做的,所以肯定会生成一棵子集树。就是代码中的search函数,可以看到从0到2*num的长度尝试了所有的0 1搭配,也就是所有的可能的出栈和入栈的顺序。然后把所有的0 1即出栈入栈存在rs数组里,其中0代表入栈,1代表出栈。此时我们可以想到,所有可能的搭配肯定是0 1个数相等的那些组合,因为将字符串出栈入栈转化成另一个字符串嘛,肯定出和入的次数要相等啊,还有一点可以想到的是:肯定先得有入栈才能有出栈即肯定先有0才能有1,不然空栈哪里来的栈顶元素来出,这都是很容易想到的。那么有了所有的出栈和入栈搭配之后,然后在test函数里面挨个检验,看那个出栈入栈的顺序得到的字符串跟目标字符串相同,那么就肯定是所求的答案之一(此时废话一句,这个答案肯定是现有0再有1而且肯定0 1的个数相同)。这个其实也用的是很经典的回溯法一般公式,即:

a[m]=0;

search(m+1);

a[m]=1;

search(m+1);

最后得到所有可能的结果,然后逐一检验。跟0 1背包问题,装载问题本质上都一样。废话不多说,代码如下:

#include<iostream>
#include<stack>
#include<stdio.h>
#include<string.h>
using namespace std;
char str1[100],str2[100];
int judge[100];
int len1,len2;
stack<char>s;
int test()
{
    int i,j=0,k=0,flag=1,len=0;
    char temp[100];
    for(i=0;i<2*len1;i++)
    {
        len=len+judge[i];//首先,把当前树的序列号全部加起来
    }
    if(len!=len1)
    {
        flag=0;//如果不等于原字符串长度,就令flag等于0
    }//因为可能的序列肯定是0 1的个数相等而且加起来等于字符串长度
    for(i=0;i<2*len1;i++)
    {
        if(judge[i]==1)
        {//对于当前枝干的每一个序列号,如果为1就从第一个字符开始把字符串入栈
            s.push(str1[j]);
            j++;
        }
        if(judge[i]==0)
        {//如果哪一个为0,出栈
            if(j>k)//入栈的肯定要比出栈的多
            {
                temp[k]=s.top();
                s.pop();
                k++;
            }
            else
            {
                flag = 0;
                break;
            }
        }
    }
    for(k=0;k<len1;k++)
    {
        if(temp[k]!=str2[k])
        {
            flag = 0;
            break;
        }
    }
    return(flag);
}
void output()
{
    int i ;
    for(i=0;i<2*len1-1;i++)
    {
        if(judge[i]==1)
            cout<<“i “;
        else
             cout<<“o “;
    }
    if(judge[2*len1] == 1)
        cout<<“i”<<endl;
    else
        cout<<“o”<<endl;
}
void search(int m)
{//搜索函数的作用,生成一棵树,根据字符串的长度,生成二倍长的数有所有的组合
    int i;
    if(m==2*len1) //递归结束
    {
        if(test())//生成完之后进行test检验,若检验成功,就输出结果
            output();
    }
    else
    {
        judge[m]=1;
        search(m+1);
        judge[m]=0;
        search(m+1);
    }
}
int main()
{
    while(scanf(“%s”,str1) != EOF)
    {
        scanf(“%s”,str2);
        len1=strlen(str1);
        len2=strlen(str2);
        while(!s.empty())//如果不是空,就清空栈
            s.pop() ;
        if(len1!=len2)//若两个字符串长度不相等,那么肯定不能匹配
            cout<<“[“<<endl<<“]”<<endl;
        else
        {
            cout<<“[“<<endl;//若相等,则搜索
            search(0);
            cout<<“]”<<endl;
        }
    }
    return 0;
}
 

 

 

 

 

 

 

 

 

    原文作者:回溯法
    原文地址: https://blog.csdn.net/zhuge2017302307/article/details/86255853
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞