P1032 字串变换

在这里插入图片描述
在这里插入图片描述

题目本身其实并不难,但是细节特别特别多。。。。,我因为细节问题踩坑踩了一个小时,自从接触了C++,真的很有感触STL大法好

这道题使用广搜的算法,首先自然是一个结构体,里面存放当前字符串和到达当前字符串所需要的步数。首先将初始的字符串设置为A,当前步数设置为0,入队,开始广搜,每次从队列弹出一个元素,判断当前的字符串是否等于B并且当前到达当前的步数是否小于10,如果满足条件就保存结果退出,如果当前步数大于10,果断退出,上面两个条件都不满足的情况下,当前弹出队列的那个结构体元素,判断其字符串是否有子串可以转换为新的字符串,如果有就将转换后的字符串加入队列,并将其步数在上一步的基础上+1

这里要注意!!!几个踩坑的地方,如果当前的步数小于10步,但是队列已经为空了,那么上面的结束条件都不会满足,退出后res=0,但是实际上此时是无解的,所以最后还有一个特判,如果将弹出的结构体的字符串转换后,队列仍然为空,说明已经不能转换了,就将res设置为-1

**踩坑点2. **
program procedure
g ce
ra dur
am ee
ee am

最开始第一个入队的元素是program,那么其可以转换为proceram,progdurm,progree,这个自然没问题,但是还有这种情况!!

abaaaba abcdaba
a b
b d
d e
e f
f g
g c

这种情况,最开始第一个入队元素是abaaaba,然后看看转换规则,对于第一个转换规则a–>b,这里面可以转换5次,当时我只用str1.find(str2),匹配到第一个以后就不管了,其实后面还有可以匹配的,所以我们要使用str.find(str2,i)这里的i的范围是0–str.size()-1,并不是匹配到第一个就不管了,后面还有可以匹配的,对于判重的问题直接使用map就完事了,每次将转换后的标记为1,map[str]=1, 后面再有转换的时候判断一下map[str]是否等于1,如果等于就直接跳过,如果不等于就将其加入容器并标记为1

这种题目其实并不难,但是要注意的细节太多了,下面是AC代码~

#include<iostream>
#include <queue>
#include <map>
using namespace std;
#define  Max 50
string a,b;//将a转换为b
string org[Max],obj[Max];
typedef pair<string,int> Node; //当前的字符串和步数
int res;//保存结果
int n=1;//转换的次数
void  trans(string str,vector<string> &t);//看看str 里面有没有需要转换的
void bfs();
map<string,int > f; //去重
    int main()
    {
        cin>>a>>b;
        while(cin>>org[n]>>obj[n])
        {
            n++;
        }
        n--;
        bfs();
        if(res==-1)
        {
            cout<<"NO ANSWER!"<<endl;
        } else
        {
            cout<<res<<endl;
        }
        return 0;
    }

    void bfs()
    {
        Node node;
        node.first=a;
        node.second=0;
        queue<Node> t;
        t.push(node);
        while(!t.empty())
        {
            Node temp=t.front();
            t.pop();
            if(temp.first==b&&temp.second<=10)
            {
                res=temp.second;
                return ;
            }
            else if(temp.second>10)
            {
                res=-1;
                return ;
            }
            else
            {
                vector<string > vec;
                trans(temp.first,vec);
                for(vector<string>::iterator it=vec.begin();it!=vec.end();it++)
                {
                    node.first=*it;
                    node.second=temp.second+1;
                    t.push(node);
                }
                if(t.empty()) //如果加入后队列仍然然为空,说明其变化在小于10步之前已经为空
                {
                    res=-1;
                    return ;
                }
            }
        }
    }


    void  trans(string str,vector<string> &vec)//看看beq里面有没有需要转换的
    {
        vec.clear();
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=str.size()-1;j++)
            {
                string temp=str;
                int nx=str.find(org[i],j);//从j号位置开始匹配
                if(nx!=string::npos)
                {
                    string t=temp.replace(nx,org[i].size(),obj[i]);//将nx开始的org[i].size()个字符替换成obj[i]
                    if(f[t]==0)  //剪枝
                    {
                        vec.push_back(t);
                        f[t]=1;
                    }

                }
            }

        }
        return ;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值