题目描述
已知有两个字串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数据类型的常用操作