P1032 字串变换 (字符串,bfs)

题目描述

已知有两个字串 A, B 及一组字串变换的规则(至多6个规则):

A1 -> B1

A2 -> B2

规则的含义为:在 A$中的子串 A1 可以变换为 B1、A2 可以变换为 B2 …。

例如:A='abcd'B='xyz'

变换规则为:

‘abc’->‘xu’‘ud’->‘y’‘y’->‘yz’

则此时,A 可以经过一系列的变换变为 B,其变换的过程为:

‘abcd’->‘xud’->‘xy’->‘xyz’

共进行了三次变换,使得 A 变换为B。

输入输出格式

输入格式:

输入格式如下:

A B A1 B1

A2 B2 |-> 变换规则

... ... /

所有字符串长度的上限为 20。

输出格式:

输出至屏幕。格式如下:

若在 10 步(包含 10步)以内能将 A 变换为 B ,则输出最少的变换步数;否则输出"NO ANSWER!"

输入输出样例

输入样例#1:
abcd xyz
abc xu
ud y
y yz
输出样例#1: 
3
这个题目我一开始根本不知道怎么做...想起来cf有个c题跟这个题面好像(其实很不一样)这个题其实也是搜索,只不过路径变成了字符串的形式转换。做法其实就是把母串(a)从第一个字符开始bfs,思路很简单,但是需要注意的不少,首先是字符串的处理,在学了一堆string的操作函数之后,变换字符串容易多了;然后就是优化时间,因为如果母串里有重复的一段子串,那么它们分别进入队列bfs后,就会出现走出重复路径的现象,所以在同一位置的某一子串只需要变化一次就够了,然后又有map这个容器,可以把string和访问次数对应起来,访问过的子串就不再访问了。据说这个题目可以用双向bfs 可是感觉这样连b串都需要转换一下...太复杂了...就放弃了(其实是嫌麻烦)
#include<bits/stdc++.h>

using namespace std;

int n,ans;
string a,b;
string x[25],y[25];
map<string,int>vis;

struct node
{
    string t;
    int step;
};

string convert(const string &s,int pos,int k)               //按运算规则转换母串
{
    string temp="";
    if(s.length()<pos+x[k].length())    return temp;
    for(int i=0; i<x[k].length(); i++)
    {
        if(s[pos+i]!=x[k][i])
            return temp;
    }
    temp=s.substr(0,pos);                                  //string类可以直接运算真的太方便了
    temp+=y[k];
    temp+=s.substr(pos+x[k].length());                     //sbustr(pos)取从pos开始的子串
    return temp;
}

void bfs()
{
    queue<node> q;
    node s;
    s.t=a;
    s.step=0;
    q.push(s);
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        string temp;
        if(vis.count(now.t)==1) continue;
        if(now.t==b)
        {
            ans=now.step;
            break;
        }
        vis[now.t]=1;
        for(int i=0; i<now.t.length(); i++)       //逐个字符搜索
            for(int j=0; j<n; j++)                //逐个转换方式搜索
            {
                temp=convert(now.t,i,j);
                if(temp!="")
                {
                    node next;
                    next.t=temp;
                    next.step=now.step+1;
                    q.push(next);
                }
            }
    }
    if(ans>0 && ans<=10)
        cout<<ans<<endl;
    else
        cout<<"NO ANSWER!"<<endl;
}

int main()
{
    cin>>a>>b;
    while(cin>>x[n]>>y[n])         //不知道多少组数据 只剩ctrl+z结束输入
        n++;
    bfs();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/youchandaisuki/p/8700921.html