惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
小众软件
小众软件
J
Java Code Geeks
I
InfoQ
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
L
LangChain Blog
博客园 - 司徒正美
量子位
Y
Y Combinator Blog
C
Check Point Blog
T
Tailwind CSS Blog
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
A
About on SuperTechFans
B
Blog RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
V
V2EX
阮一峰的网络日志
阮一峰的网络日志

博客园 - zealsoft

洛谷 P1816 忠诚题解 洛谷 P2384 最短路题解 洛谷 P2725 邮票题解 洛谷 P2722 总分题解 洛谷 P1219 八皇后题解 洛谷 P2921 在农场万圣节Trick or Treat on the Farm题解 洛谷 P1162 填涂颜色题解 洛谷 P1330 封锁阳光大学题解 洛谷 P1443 马的遍历题解 洛谷 P1280 尼克的任务题解 洛谷 P1020导弹拦截题解 洛谷 P1141 01迷宫题解 VisualSVNServer无法卸载也无法安装,报告不是有效的MOF文件(0x8004401e)错误 视频捕捉的格式问题 一个VxWorks源代码网站 找个轻量级的Log库还挺难 TAU G2中的BitString和OctetString W32.Downadup.autorun病毒的清除 如何用Visual Studio 2005编译Wireshark的插件
洛谷 P1032 字串变换题解
zealsoft · 2019-08-11 · via 博客园 - zealsoft

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

题目描述

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

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

这是一个字符串操作的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