题目链接:https://www.luogu.org/problem/P1032

题目描述

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

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

A_1A1 ->B_1B1

A_2A2 -> B_2B2

规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1A_2A2 可以变换为 B_2B2 …。

例如:A=abcd,B=xyz

变换规则为:

abcxuudyyyz

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

abcdxudxyxyz

共进行了33次变换,使得AA变换为BB。

输入格式

输入格式如下:

ABB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则

... ... /

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

输出格式

输出至屏幕。格式如下:

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

输入输出样例

输入 #1复制
abcd xyz
abc xu
ud y
y yz
输出 #1复制
3

题解

这是一个字符串操作的BFS。和前面做过的01迷宫马的遍历相比,每次变化就相当于一次移动,而变换前后的字符串就相当于迷宫中的格点。使用STL中的string类进行find和replace操作还是相当方便的。在前面的例题中使用bool数组来描述是否遍历过某个格点,而这里使用一个map数组来描述是否遍历过某个字符串操作结果。下面是代码。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
#include <map>

using namespace std;

struct Node
{
    string x;
    int step;
};
Node q[100005];

const int MAXN = 1005;
int cnt = 0, step, front, rear; 
string n, m, a[MAXN], b[MAXN];
map<string, bool> vis; //作用等同于数组中的vis数组 

int bfs()
{
    Node now;
    now.x = n;
    now.step = 0;
    front = rear = 0;
    q[rear] = now;
    rear++;
    while(front < rear)
    {
        now = q[front++];
        if(now.x == m)
        {
            cout << now.step << endl;
            return 0;
        }
        if(now.step > 10)
        {
            return -1;
        }
        for(int i = 0; i < cnt; i++)
        {
            string temp = now.x;
            int pos = temp.find(a[i]);
            while(pos != -1) 
            {
                temp.replace(pos, a[i].length(), b[i]); //做变换 = pos 
                if(vis[temp] == 0) 
                {
                    vis[temp] = true;
                    q[rear].x = temp;
                    q[rear].step = now.step + 1;
                    rear++;
                }
                temp = now.x; 
                pos = temp.find(a[i], pos + 1); // 从下一个位置查找,做一次变换
            }
        } 
    }
    return -1;
}
    
int main()
{
    cin >> n >> m;
    cnt = 0;
    while(cin >> a[cnt] >> b[cnt])
    {
        cnt++;
    }
    if(bfs() < 0)
    {
        cout << "NO ANSWER!" << endl;
    }
    return 0;
}

程序里面另外一个需要注意的是,A字符串中可能存在多个变换的子串,我们需要每次变换其中的一个。有一个测试例是专门卡这种情况的:

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

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄