字串变换 (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 在河上有一 ...
随机推荐
- 企业架构与建模之使用ArchiMate进行分析
企业架构与建模之使用ArchiMate进行分析(全系列完) 4. 使用ArchiMate进行分析 正如前面所说的那样,一个企业整体效率的提升有时并不是通过某一个领域内的优化就能达到的,而且这种忽视全局 ...
- C# 毛玻璃效果
- Microsoft Message Analyzer (微软消息分析器,“网络抓包工具 - Network Monitor”的替代品)官方正式版现已发布
Microsoft Message Analyzer (微软消息分析器,“网络抓包工具 - Network Monitor”的替代品)官方正式版现已发布 来自官方日志的喜悦 被誉为全新开始的消息分析器 ...
- canvas 之刮刮卡
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Xilinx-Zynq Linux内核源码编译过程
本文内容依据http://www.wiki.xilinx.com网址编写,编译所用操作系统为ubuntu 14 1.交叉编译环境的安装配置 1)http://www.wiki.xilinx.com/I ...
- Github官方app分析——用户身份验证模块
这篇文章记述的是我对Giuhub官方app的用户身份验证模块的分析. Giuhub的官方app虽然是一个非常小众的程序,但是从程序的设计的角度看,这是一个非常优秀的项目.对于其用户身份验证模块,给我留 ...
- springMVC之数据传递
在前面介绍过从controller中向页面中传数据,可以通过HttpServletRequest进行setAttribute可以将数据放入request中.并且可以在jsp页面使用el表达式获取数据. ...
- 结构-行为-样式-angularJs ngAnimate(Js实现)
声明 页面 Js 注意事项 官方链接 一.声明 注意animate的版本要与Angular的一致. <script src="jquery.1.9.1.min.js"> ...
- UOJ#117. 欧拉回路
#117. 欧拉回路 题目描述 有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次. 一共两个子任务: 这张图是无向图.(50分) 这张图是有向图.(5 ...
- IOS网络请求中文转码
-(void)get { NSString *urlStr = @"http://120.25.226.186:32812/login2?username=小码哥&pwd=520it ...