字串变换 (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 在河上有一 ...
随机推荐
- CSS中文字体的英文名称 – 前台开发必备
做什么用的?写过CSS的都晓得,一般用在font-family后面——为什么不用中文呢?有过一定开发经验的都晓得CSS里面用中文也是会乱码的,特别是没有中文字符集的浏览器,直接成了框框,用英文就可以解 ...
- easyuidatagrid扩展--玩一下,无实际意义
直接上代码 $.extend($.fn.datagrid.defaults.editors, { operater: { init: function (container, options) { v ...
- Devexpress XtraReports 交叉报表
[原创]Devexpress XtraReports 系列 5 创建交叉报表 昨天我们已经介绍了如何创建多栏报表,详见:[原创]Devexpress XtraReports 系列 4 创建多栏报表 ...
- Hibernate之AbstractEntityPersister
Hibernate开发中需要根据持久层对象获取所映射的数据库表相关信息,如表名,主键,外键对象等相关系. Hibernate配置 Hibernate.cfg.xml <?xml version= ...
- LESS编译方案
我的LESS编译方案 2013-08-07 10:22 by 逆风之羽, 469 阅读, 2 评论, 收藏, 编辑 背景 近期项目前端决定使用less,简单介绍一下,详细信息有兴趣查看官方文档(htt ...
- 一个方便且通用的导出数据到 Excel 的类库
一个方便且通用的导出数据到 Excel 的类库 起源: 之前在做一个项目时,客户提出了许多的导出数据的需求: 导出用户信息 导出业务实体信息 各种查询都要能导出 导出的数据要和界面上看到的一致 可以分 ...
- escape,encodeURI,encodeURIComponent函数比较
escape,encodeURI,encodeURIComponent函数比较 js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数 ...
- Objective-C之run loop详解
Objective-C之run loop详解 做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一门语言还是需要深 ...
- Magnum Kuernetes源码分析(一)
Magnum版本说明 本文以magnum的mitaka版本代码为基础进行分析. Magnum Kubernetes Magnum主要支持的概念有bay,baymodel,node,pod,rc,ser ...
- 【转载】深入Java单例模式
原文出处:http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就 ...