题目描述
已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):
A_1A
1
-> B_1B
1
A_2A
2
-> B_2B
2
规则的含义为:在 AA中的子串 A_1A
1
可以变换为 B_1B
1
,A_2A
2
可以变换为 B_2B
2
…。
例如:AA=’abcdabcd’BB=’xyzxyz’
变换规则为:
‘abcabc’->‘xuxu’‘udud’->‘yy’‘yy’->‘yzyz’
则此时,AA可以经过一系列的变换变为BB,其变换的过程为:
‘abcdabcd’->‘xudxud’->‘xyxy’->‘xyzxyz’
共进行了33次变换,使得AA变换为BB。
输入输出格式
输入格式:
输入格式如下:
AA BB
A_1A
1
B_1B
1
A_2A
2
B_2B
2
|-> 变换规则
… … /
所有字符串长度的上限为2020。
输出格式:
输出至屏幕。格式如下:
若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出”NO ANSWER!”
输入输出样例
输入样例#1:
abcd xyz
abc xu
ud y
y yz
输出样例#1:
3
中文题就不写题意了。。。
思路:
裸广搜,没剪枝。
然而作为一个蒟蒻,我选择了狂用STL解决这题,于是出现了各种奇奇怪怪的问题,各种奇奇怪怪的函数不会写。。。
借此机会记录一下STL的string,set的用法:
string:
1 -> insert(pos, str),这里pos可以是从0开始的字符串下标,或者一个指针,表示在这一位的字符之前插入str,即str的开头在被插入的字符串中下标是pos
2 -> erase(pos, len),从pos开始删除len个字符(包括pos)
erase(first, last),删除[first, last)区间字符
3 -> find(str, pos),在原string的pos位开始(包括pos),寻找str,返回一个string::size_type,若找不到则返回string::npos,比较达克,记住就好了。
set:
1 -> insert(val)其他有些操作比较达克我还是不记了,又要记混了
2 -> erase(it),删除it指向的元素
erase(first, last),删除[first, last)的元素
erase(val),删除值为val的元素
3 -> lower_bound(),upper_bound(),clear()都可以用
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
using namespace std;
string a, b, x[7], y[7];
int n;
struct NODE{
string s;
int step;
};
queue<NODE> q;
set<string> st;
int main()
{
cin >> a >> b;
n = 0;
while (cin >> x[++n] && cin >> y[n]);
q.push((NODE){a, 0}); st.insert(a);
while (!q.empty()){
string now = q.front().s;
int step = q.front().step;
if (now == b){
cout << step;
return 0;
}
if (step == 10) continue;
for (int i = 1; i <= n; i++){
string::size_type found = -1;
while (1){
found = now.find(x[i], found+1);
if (found == string::npos) break;
string nxt = now;
nxt.erase(found, x[i].size());
nxt.insert(found, y[i]);
if (st.find(nxt) != st.end()) continue;
st.insert(nxt);
q.push((NODE){nxt, step+1});
}
}
q.pop();
}
cout << "NO ANSWER!";
return 0;
}