当前位置: 首页 > news >正文

洛谷 P1032 [NOIP 2002 提高组] 字串变换

【题目链接】

洛谷 P1032 [NOIP 2002 提高组] 字串变换

【题目考点】

1. 广搜
2. 双向广搜

【解题思路】

解空间树中每个结点包含的状态为一个字符串s,该结点的子结点中的字符串为字符串s通过变换规则可以变化而成的字符串。求从起始字符串变换为最终字符串的最少变换步数,需要使用广搜算法。
队列中保存的元素为字符串以及起始字符串变成该字符串的变化步数。
首先将起始字符串入队,每次循环出队一个字符串u,对于每个 a i → b i a_i\rightarrow b_i aibi的变换规则,已知字符串 a i a_i ai的长度为len,枚举字符串u中所有长为len的子串,如果存在子串为 a i a_i ai,则生成将u中该子串 a i a_i ai替换为 b i b_i bi后的字符串t,判断t是否已出现过,如果t未出现过,则标记t已出现过,而后将t加入队列,变化的步数要增加1。(可以使用map或set来标记以及查询一个字符串是否已经出现过。)。
如果出队的字符串u是目标字符串,且步数小于等于10步,则返回变化步数。如果步数大于10步,则不再扩展子结点入队。

本问题也可以使用双向广搜完成,起点和终点字符串同时入队,记录从起点还是从终点出发访问某字符串。如果一个字符串经过变换后得到的字符串是已经能从另一个源头出发变换得到,那么就找到了一条从起点到终点的路径,返回路径长度。

【题解代码】

解法1:广搜

# include<bits/stdc++.h>
using namespace std;
#define N 25
struct Node
{
	string s;
	int d;
};
string st, ed, a[N], b[N];
int n;
map<string, bool> vis;
int bfs()
{
	queue<Node> que;
	vis[st] = true;
	que.push(Node{st, 0});
	while(!que.empty())
	{
		string u = que.front().s;
		int d = que.front().d;
		que.pop();
		if(d > 10)//超过10步,没有结果 
			return -1;
		if(u == ed)
			return d;
		for(int i = 0; i < n; ++i)//看a[i]->b[i] 
		{
			int len = a[i].length();
			for(int j = 0; j+len <= u.length(); ++j) if(u.substr(j, len) == a[i])
			{
				string t = u;
				t.replace(j, len, b[i]);
				if(!vis[t])
				{
					vis[t] = true;
					que.push(Node{t, d+1});
				} 
			}
		}
	}
	return -1;
}
int main()
{
	cin >> st >> ed;
	while(cin >> a[n] >> b[n])//下标从0~n-1 
		n++;
	int ans = bfs();
	if(ans == -1)
		cout << "NO ANSWER!";
	else
		cout << ans;
	return 0;
}
2. 双向广搜
#include<bits/stdc++.h>
using namespace std;
string x, y, a[10], b[10];
int n; 
map<string, int> vis, dis;
int bfs()
{
	queue<string> que;
	vis[x] = 1, vis[y] = 2;
	dis[x] = 0, dis[y] = 0;
	que.push(x);
	que.push(y);
	while(!que.empty())
	{
		string u = que.front();
		que.pop();
		for(int i = 0; i < n; ++i)
		{
			int len = a[i].length();
			for(int j = 0; j+len <= u.length(); ++j) if(u.substr(j, len) == a[i])
			{
				string t = u;
				t.replace(j, len, b[i]);
				if(vis[t] == 0)
				{
					vis[t] = vis[u];
					dis[t] = dis[u]+1;
					if(dis[t] <= 10)
						que.push(t);
				}
				else if(vis[t] != vis[u])
				{
					if(dis[t]+dis[u]+1 <= 10)
						return dis[t]+dis[u]+1;
				}
			}
		}
	}
	return -1;
}
int main()
{
	cin >> x >> y;
	while(cin >> a[n] >> b[n])
		n++;
	int ans = bfs();
	if(ans == -1)
		cout << "NO ANSWER!";
	else
		cout << ans;
	return 0;
}
http://www.dtcms.com/a/108559.html

相关文章:

  • 第一期:Spring Web MVC 入门 [特殊字符](基础概念 + 环境搭建)
  • 解锁医疗行业软件 UI 设计密码,打造高效就医体验
  • Linux NUC小主机化身视频会议服务器: 技术优势与部署实战
  • 少儿编程 中国电子学会软件编程C语言/C++等级考试二级历年真题答案解析【持续更新 已更新21题】
  • android设备出厂前 按键测试 快速实现-屏蔽Home,Power等键
  • 群体智能优化算法-鹈鹕优化算法(Pelican Optimization Algorithm, POA,含Matlab源代码)
  • 亚马逊云科技携手 DeepSeek:开启企业级生成式 AI 新征程
  • 通信算法之253: 802.16(WiMAX)的FFT-CP长度
  • 力扣HOT100之链表:160. 相交链表
  • MINIQMT学习课程Day1
  • 【操作系统】LinuxRT-Thread查看内存分布的方法
  • 06_docker 网络类型
  • 蓝桥杯 web 学海无涯(axios、ecahrts)版本二
  • tomcat使用笔记、启动失败但是未打印日志
  • ue5 学习笔记 FPS游戏制作35 GameMode与GameInstance
  • 零基础玩转深度神经网络大模型:从Hello World到AI炼金术-详解版(含:Conda 全面使用指南)
  • MySQL 管理
  • 论文阅读9——更严格的汽车排放标准对气候、健康、农业和经济的影响
  • Redis 慢查询
  • php 扩展库官网
  • 小程序中的网络请求
  • springcouldalibaba5大组件
  • leetcode热题100(2)
  • 在Linux系统上深入安装与配置Redis:从基础到高级的全方位指南
  • LeetCode BFS解决最短路问题
  • 深入浅出:Spring Bean 的初始化流程详解
  • [力扣每日一练]关于特定字符串的匹配
  • Flutter 插件 百度地图 Android插件演示
  • 配置Next.js环境 使用vscode
  • 多元守护,构筑健康生活