0
点赞
收藏
分享

微信扫一扫

洛谷 P1032 字串变换


题目描述

已知有两个字串A,BA,BA,B及一组字串变换的规则(至多666个规则):
A1A_1A1​ ->B1 B_1B1​
A2A_2A2​ -> B2B_2B2​
规则的含义为:在 AAA中的子串 A1A_1A1​ 可以变换为B1 B_1B1​,A2A_2A2​ 可以变换为 B2B_2B2​ …。
例如:A=abcd,B=xyz,
变换规则为:
abc→xu,ud→y,y→yz
则此时,AAA可以经过一系列的变换变为BBB,其变换的过程为:
abcd→xud→xy→xyz。
共进行了333次变换,使得AAA变换为BBB。

输入格式

输入格式如下:
AAA BBB
A1A_1A1​ B1B_1B1​
A2A_2A2​ B2B_2B2​ |-> 变换规则
… … /
所有字符串长度的上限为202020。

输出格式

输出至屏幕。格式如下:
若在101010步(包含101010步)以内能将AAA变换为BBB,则输出最少的变换步数;否则输出"NO ANSWER!"

输入输出样例

输入

abcd xyz
abc xu
ud y
y yz

输出

3

AC代码

#include<iostream>
#include<string>
#include<queue>
#include<map>
using namespace std;
string str_st,str_en; //串 A B
string A[7], B[7]; //可转化形式
queue<string> que; //存放待匹配字符串
queue<int> step; //与que队列对应 对应字符串所对应的匹配
map<string, int> mp; //剪枝用 (字符串是否已经被匹配过)
int n;
int bfs() {
bool bo = false; //得到最终串后退出循环的条件
while (que.empty() == 0&&step.front()<10) //队列不为空且步数小于10
{
if (mp[que.front()] == 1) //当前串被搜索过 出队
{
step.pop();
que.pop();
continue;
}
mp[que.front()] = 1; //标记被搜索的字符串
for (int i = 0; i < n; i++) //遍历转换方式
{
string str = que.front();
while (true) //循环到当前串中无当前需转换串
{
int place = str.find(A[i]); //得到子串的位置
if (place == -1) //没有子串 退出循环
break;
//获得转化后的新字符串 并将其入队
string str_1 = que.front();
str_1.replace(place, A[i].size(), B[i]);
que.push(str_1);
//消除第一次出现的子串(将母串中的当前发现子串的第一个字母换成特殊符号)
str[place] = '*';
//新串步数入栈
step.push(step.front() + 1);
//是否退出循环
if (str_1 == str_en)
{
bo = true;
break;
}
}
//是否退出循环
if (bo)
break;
}
//出队操作
que.pop();
step.pop();
//返回步数队尾元素 即最小步数
if (bo)
return step.back();
}
return 0;
}
int main() {
cin >> str_st >> str_en;
//第一个串及步数入队
que.push(str_st);
step.push(0);

while (cin >> A[n] >> B[n]) n++;
int ans = bfs();
if (ans != 0)
cout << ans << endl;
else
cout << "NO ANSWER!" << endl;
return 0;
}

本题除了掌握广度优先搜索 还要了解string数据类型的常用操作

洛谷 P1032 字串变换_字符串


举报

相关推荐

0 条评论