每周一算法:双向广搜

题目链接

字符串变换

题目描述

已知有两个字串 A , B A,B A,B,及一组字串变换的规则(至多 6 6 6个规则):
A 1 → B 1 A_1→B_1 A1B1
A 2 → B 2 A_2→B_2 A2B2

规则的含义为:在 A A A中的子串 A 1 A_1 A1 可以变换为 B 1 B_1 B1 A 2 A_2 A2可以变换为 B 2 B_2 B2…。

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

变换规则为:

abcxuudyyyz

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

abcdxudxyxyz

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

注意,一次变换只能变换一个子串,例如 A = A= A=aa B = B= B=bb

变换规则为:

ab

此时,不能将两个 a 在一步中全部转换为 b,而应当分两步完成。

输入格式

A B A~~B A  B
A 1 B 1 A_1~B_1 A1 B1
A 2 B 2 A_2~B_2 A2 B2
… …

第一行是两个给定的字符串 A A A B B B

接下来若干行,每行描述一组字串变换的规则。

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

输出格式

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

输入样例

abcd xyz
abc xu
ud y
y yz

输出样例

3

算法思想

根据题目描述,通过输入的规则将字串 A A A变换为 B B B,求最小步数,显然可以通过BFS求解。

分析数据范围,至多 6 6 6个规则,在 10 10 10 步(包含 10 10 10步)以内进行转换,如果直接进行BFS,在最坏情况下搜索的状态空间是 6 10 6^{10} 610,会超时,可以使用双向广搜进行处理。

双向广搜,是指从起点和终点同时开始进行BFS,双向奔赴直到找到共同的目标为止。

使用双向广搜可以把搜索空间降到 2 × 6 5 2\times 6^5 2×65,大大减少了要搜索的状态,剪枝效果明显。

使用双向广搜时要注意:

  • 在双向广搜时,优先选择队列中状态数量较少的方向来扩展,可以优化搜索效率
  • 在扩展时,需要将一层的所有节点扩展完,不能只扩展一个点。如下图所示,第 2 2 2层有 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4四个节点,则需要把这 4 4 4个节点从队列中全部取出进行扩展。否则,找到的可能不是最少的转换次数。
    在这里插入图片描述

代码实现

#include <iostream>
#include <queue>
#include <cstring>
#include <unordered_map>
using namespace std;
const int N = 6;
int n;
string A, B; //起点和终点
string a[N], b[N]; //变换规则
//从队列q中,将同层的节点全部扩展
int extend(queue<string>& q, unordered_map<string, int>& da, unordered_map<string, int>& db, string a[N], string b[N])
{int d = da[q.front()]; //层数while(q.size() && da[q.front()] == d) //将同层的节点全部扩展{string t = q.front(); q.pop();for(int i = 0; i < n; i ++) //枚举在原字符串中使用替换规则for(int j = 0; j < t.size(); j ++) //枚举替换位置if(t.substr(j, a[i].size()) == a[i]) //存在可以替换的子串{string r = t.substr(0, j) + b[i] + t.substr(j + a[i].size()); //替换后的字符串if(db.count(r)) return da[t] + db[r] + 1;//如果反方向已经搜索到该字符串,则搜索结束,返回步数if(da.count(r)) continue; //之前已经搜索过r了da[r] = da[t] + 1;q.push(r);}}return 11;
}
int bfs()
{if(A == B) return 0;//双向搜索,扩展时分别进入不同队列queue<string> qa, qb;//da、db分别存储变换后的字符串到起点A和终点B的转换次数unordered_map<string, int> da, db;qa.push(A), qb.push(B); //起点和终点插入队列da[A] = db[B] = 0;int step = 0; //转换次数while(qa.size() && qb.size()) //两个队列都不为空{int t;if(qa.size() < qb.size()) //优先搜索状态数较少的方向t = extend(qa, da, db, a, b);elset = extend(qb, db, da, b, a);if(t <= 10) return t;if(++ step == 10) return -1; //变换10次没有结果}return -1;
}
int main()
{cin >> A >> B;while(cin >> a[n] >> b[n]) n ++;int t = bfs();if(t == -1) puts("NO ANSWER!");else cout << t << '\n';return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch统计属性

目录 1.normal2. mean, sum, min, max, prod3.argmin, argmax4. topk kthvalue5. compare 1.normal torch.normal(mean, std, *, generatorNone, outNone) → Tensor返回一个张量&#xff0c;其中的每个元素随机来自独立的标准正态分布。这些分布具有给定的均值和标准差。 参数…

【cmu15445c++入门】(13)C++的std::promise

一、说明 std::promise 是C11并发编程中常用的一个类&#xff0c;常配合std::future使用。其作用是在一个线程t1中保存一个类型typename T的值&#xff0c;可供相绑定的std::future对象在另一线程t2中获取 二、代码 #include <chrono> #include <future> #includ…

Hive SQL 开发指南(二)使用(DDL、DML,DQL)

在大数据领域&#xff0c;Hive SQL 是一种常用的查询语言&#xff0c;用于在 Hadoop上进行数据分析和处理。为了确保代码的可读性、维护性和性能&#xff0c;制定一套规范化的 Hive SQL 开发规范至关重要。本文将介绍 Hive SQL 的基础知识&#xff0c;并提供一些规范化的开发指…

如何安装ProtoBuf环境

1 &#x1f351;下载 ProtoBuf&#x1f351; 下载 ProtoBuf 前⼀定要安装依赖库&#xff1a;autoconf automake libtool curl make g unzip 如未安装&#xff0c;安装命令如下&#xff1a; Ubuntu ⽤⼾选择&#xff1a; sudo apt-get install autoconf automake libtool cur…

Unity 向量计算、欧拉角与四元数转换、输出文本、告警、错误、修改时间、定时器、路径、

using System.Collections; using System.Collections.Generic; using UnityEngine;public class c2 : MonoBehaviour {// 定时器float t1 0;void Start(){// 向量Vector3 v1 new Vector3(0, 0, 2);Vector3 v2 new Vector3(0, 0, 3);// 计算两个向量的夹角Debug.Log(Vector3…

Java 学习和实践笔记(26):组合(component)的含义以及与继承(extends)的关系

组合的两个作用&#xff1a; 1&#xff09;通过将父类对象作为子类的属性 2&#xff09;通过第1点的作用&#xff0c;实现了代码复用。 示例代码&#xff1a; public class TestComponent {public static void main(String[] args) {Student2 s1 new Student2("jason&…

灯塔:HTML笔记

网页由哪些部分组成&#xff1f; *文字 图片 音频 视频 超链接 程序员写的代码是通过浏览器转换成网页的 五大浏览器有哪些&#xff1f; *IE浏览器 *火狐浏览器&#xff08;Firefox&#xff09; *谷歌浏览器&#xff08;Chrome&#xff09; *Safari浏览器 *欧朋浏览器&…

NENU OJ算法2例题||搜索E

NENU OJ算法2例题 合集原文指路 算法2搜索E 1281: E001 数的划分 题目描述 将整数n分成k份&#xff0c;且每份不能为空&#xff0c;任意两种分法不能相同&#xff08;不考虑顺序&#xff09;。 例如&#xff1a;n7&#xff0c;k3&#xff0c;下面三种分法被认为是相同的。…

【数据结构与算法】动态规划法解题20240302

这里写目录标题 一、198. 打家劫舍1、动态规划五部曲 二、213. 打家劫舍 II 一、198. 打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间…

【python】双十一美妆数据分析可视化 [聚类分析/线性回归/支持向量机](代码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【JavaSE】 P165 ~ P194 抽象方法,抽象类,接口,接口内容,多接口实现和父类继承,多态,向上转型,向下转型

目录 抽象抽象的概念抽象方法和抽象类的格式抽象方法和抽象类的使用抽象方法和抽象类的注意事项● 练习1. 写一个父类图形类&#xff0c;其中有方法&#xff0c;功能计算面积为抽象方法。2. 抽象类继承。判断对错,没错的分析运行结果3. 发红包,群内用户类作为父类&#xff0c;有…

NX二次开发:ListingWindow窗口的应用

一、概述 在NX二次开发的学习中&#xff0c;浏览博客时发现看到[社恐猫]和[王牌飞行员_里海]这两篇博客中写道有关信息窗口内容的打印和将窗口内容保存为txt,个人人为在二次开发项目很有必要&#xff0c;因此做以下记录。 ListingWindow信息窗口发送信息四种位置类型 设置Listi…

鸿蒙系统的开发与学习:一、安装工具与处理报错

前言&#xff1a; 鸿蒙系统的学习与记录。 1 、使用开发工具&#xff1a;deveco-studio 1&#xff09;这个是工具的安装 2&#xff09;这个是工具包&#xff0c;里面包含了 obpm&#xff0c;如果你装不上这个&#xff0c;可以使用工具包内部的 2、安装 官方安装教程&#xff…

前端学习第三天-css基础

1. CSS简介 从HTML被发明开始&#xff0c;样式就以各种形式存在。不同的浏览器结合它们各自的样式语言为用户提供页面效果的控制。最初的HTML只包含很少的显示属性。 随着HTML的成长&#xff0c;为了满足页面设计者的要求&#xff0c;HTML添加了很多显示功能。但是随着这些功能…

USB4之ASM2464PD与ASM2464PDX兼容与运用

首先在NVMe上运用: 一&#xff1a;ASM2464PD&#xff08;现在可以做带PD的方案&#xff09; 二&#xff1a;ASM2464PDX 1&#xff1a; Application Guide- CFX card reader NVMe SSD 2&#xff1a;ASM2464PDX Application Guide- NVMe SSD x4 with data clone 三&#xff…

C习题003:球筐投球(一排)

题目 输入样例 在这里给出一组输入。例如&#xff1a; 5 3 7 5 7 7 3 1 5 3 1 5 2 4 4 4输出样例 在这里给出相应的输出。例如&#xff1a; 12 10 12 16 8代码长度限制 16 KB 时间限制400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int…

新一代湖仓集存储,多模型统一架构,高效挖掘数据价值

星环科技TDH一直致力于给用户带来高性能、高可靠的一站式大数据基础平台&#xff0c;满足对海量数据的存储和复杂业务的处理需求。 同时在易用性方面持续深耕&#xff0c;降低用户开发和运维成本&#xff0c;让数据处理平民化&#xff0c;助力用户以更便捷、高效的方式去挖掘数…

jmeter如何请求访问https接口

添加线程组http请求 新建线程组&#xff0c;添加http请求 填入协议&#xff0c;ip&#xff0c;端口&#xff0c;请求类型&#xff0c;路径&#xff0c;以及请求参数&#xff0c;查看结果树等。 然后最关键的一步来了。 导入证书 步骤&#xff1a;获取证书&#xff0c;重新生…

基于SSM的高校竞赛和考级查询系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的高校竞赛和考级查询系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Sp…

Java中的动态代理与Spring AOP编程

第一章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;在Java里&#xff0c;动态代理和Spring AOP&#xff08;面向切面编程&#xff09;是两个能让代码更加灵活、更加干净的强大工具。作为一名Java程序员&#xff0c;小黑觉得掌握它们对于写出高质量的代码来说非常…