字串变换 (2002 年NOIP全国联赛提高组)
一道看似非常水的题
大意 :将一个字串 经过几种变换规则变为给定的另一个子串 ,求最小操作数。
已知有两个字串 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。
思路:从前从后双向BFS 不加限制 若递归次数等于10次仍未找到答案时,输出NO ANSWER 。其他的若替换完后 从 前端BFS的串 在从后端BFS出现过,则此时递归次数乘2减一即为答案, 从后端BFS的情况同上。 具体实现,就按照题意来,依次扫描变换规则,进行替换,替换完的字串加入队列。
双向BFS
#include <iostream>
#include <cstring>
#include <map>
#include <cstdio>
using namespace std;
const int Max = ;
string A, B;
string s_change [][], Front[Max], Back[Max];
int Limit = , head_Front = , tail_Front = , tail_Back = , head_Back = , tot = ;
map < string , int > Map_Front;
map < string , int > Map_Back;
void BFS ()
{
tot++; //记录递归次数
string s, s_replace; // s是 变换后的字串 ,s_replace 是当前需变换的字串
int head, tail;
head = head_Front; //调整指针
tail = tail_Front;
for (int i = head; i <= tail; i++)
for (int j = ; j <= Limit; j++) //变换种数 ,变为不同的替换规则
{
int change_Front = ;
while (change_Front != -) //每个字串中可以替换的字串不止一个
{
s_replace = Front [i]; //取出当前需被变换的字串
change_Front = s_replace.find (s_change [j][], change_Front ); //查找变换规则 ,change_Front是 当前规则 出现的位置
if (change_Front >= )
{
s = s_replace.replace (change_Front, s_change [j][].length(), s_change [j][]); //进行替换, s存的是替换完的字串
if (Map_Front [s] == ) //剪枝 ,若该字串出现过,则不进入队列
{
if (Map_Back [s] != ) //如果能在中间遇到,就直接输出答案
{
cout << tot * - ;
return ;
}
Front [++tail_Front] = s; //加入队列
Map_Front [s] = ; //标记为出现过
}
}
if (change_Front != -) change_Front += s_change[j][].length(); //寻找下一个字串
}
}
head_Front = tail + ; //同上 ,不过是从后面进行BFS
head = head_Back;
tail = tail_Back;
for (int i = head; i <= tail; ++i)
for (int j = ; j <= Limit; ++j)
{
int change_Back = ;
while (change_Back != -)
{
s_replace = Back[i];
change_Back = s_replace.find (s_change[j][], change_Back);
if (change_Back >= )
{
s = s_replace.replace (change_Back, s_change [j][].length(), s_change[j][]);
if (Map_Back[s] == )
{
if(Map_Front[s] != )
{
cout << tot * ;
return ;
}
Back[++tail_Back] = s;
Map_Back[s] = ;
}
}
if (change_Back != -) change_Back = change_Back + s_change [j][].length();
}
}
head_Back = tail + ;
if (tot == ) //以十次为限,若十次后仍未找到,则输出NO ANSWER
{
cout << "NO ANSWER!";
return;
}
BFS ();
}
int main()
{
ios::sync_with_stdio (false);
cin >> A >> B;
while (cin >> s_change[Limit][] >> s_change [Limit][]) Limit++;
Limit--; // 替换的组数
Map_Front [A] = ; //用 map 记录
Map_Back [B] = ;
Front [] = A; //加入队列
Back [] = B;
BFS ();
return ;
}
注意:此题属于那种看似很水,但是实现有难度的题。。
字串变换 (2002 年NOIP全国联赛提高组)的更多相关文章
- 1099 字串变换 2002年NOIP全国联赛提高组
1099 字串变换 2002年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 已知有 ...
- codevs 1098 均分纸牌 2002年NOIP全国联赛提高组 x
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必 ...
- 1009 产生数 2002年NOIP全国联赛普及组
1009 产生数 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给出一个整数 n(n< ...
- Codevs 1010 过河卒 2002年NOIP全国联赛普及组
1010 过河卒 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 如图,A 点有一个过河卒 ...
- 1008 选数 2002年NOIP全国联赛普及组
1008 选数 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description ...
- 1010 过河卒 2002年NOIP全国联赛普及组codevs
1010 过河卒 2002年NOIP全国联赛普及组codevs 题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点 ...
- Codevs 1171 潜伏者 2009年NOIP全国联赛提高组
1171 潜伏者 2009年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description [问题描述] R 国和S 国正陷 ...
- 1154 能量项链 2006年NOIP全国联赛提高组 codevs
1154 能量项链 2006年NOIP全国联赛提高组 codevs 题目描述 Description 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头 ...
- 过河 2005年NOIP全国联赛提高组(离散化+dp)
1105 过河 2005年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在河上有一 ...
随机推荐
- [转]Inside Swift
原文地址:http://www.eswick.com/2014/06/inside-swift/ Inside Swift Swift is Apple's new programming lan ...
- vs中web配置可浏览json数据文件
在日常的前端开发中,我们会制作一些数据文件,常用的有后缀名为json的文件,但是vs在启动项目时,是不能浏览json文件的,常见的错误提示如下图所示 解决这个错误,只需要在web.config文件中配 ...
- AspNetWebApi管线中如果定义两种类型的消息处理程序(全局/路由)
AspNetWebApi管线中如果定义两种类型的消息处理程序(全局/路由) 在AspNetWebApi管线中存在两种类型的消息处理程序(Message Handler) 1.全局消息处理程序,所有的请 ...
- SQL Server中日志
再谈SQL Server中日志的的作用 简介 之前我已经写了一个关于SQL Server日志的简单系列文章.本篇文章会进一步挖掘日志背后的一些概念,原理以及作用.如果您没有看过我之前的文章,请参阅: ...
- JDBC之事务隔离级别以及ACID特性
JDBC之事务隔离级别以及ACID特性 事务隔离级别: 1.更新遗失(Lost update) 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了.这是因为系统没有 ...
- Redis系统学习 四、超越数据结构
5种数据结构组成了Redis的基础,其他没有关联特定数据结构的命令也有很多.我们已经看过一些这样的命令:info,select,flushdb,multi,exec,discard,watch,和ke ...
- ASP.NET WebAPI HTTPS
参照文档 http://southworks.com/blog/2014/06/16/enabling-ssl-client-certificates-in-asp-net-web-api/ 第一 ...
- d指针在Qt上的应用及实现
Qt为了使其动态库最大程度上实现二进制兼容,引入了d指针的概念.那么为什么d指针能实现二进制兼容呢?为了回答这个问题,首先弄清楚什么是二进制兼容?所谓二进制兼容动态库,指的是一个在老版本库下运行的程序 ...
- About Spring
“Spring is the most popular application development framework for enterprise Java.”这是Spring官方首页上的第一句 ...
- MFC中菜单变灰的问题
MFC中菜单变灰 方法1:有UpdateCmdUI句柄时 定义一个BOOL变量m_b来标志菜单项是否有效, 该菜单项响应UPDATE_COMMAND_UI消息,在消息处理函数中pCmdUI->E ...