已知有两个字串 AA, BB 及一组字串变换的规则(至多 66 个规则):
A1→B1A1→B1
A2→B2A2→B2
…
规则的含义为:在 AA 中的子串 A1A1 可以变换为 B1B1、A2A2 可以变换为 B2…B2…。
例如:AA=abcd BB=xyz
变换规则为:
abc →→ xu ud →→ y y →→ yz
则此时,AA 可以经过一系列的变换变为 BB,其变换的过程为:
abcd →→ xud →→ xy →→ xyz
共进行了三次变换,使得 AA 变换为 BB。
输入格式
输入格式如下:
AA BB
A1A1 B1B1
A2A2 B2B2
… …
第一行是两个给定的字符串 AA 和 BB。
接下来若干行,每行描述一组字串变换的规则。
所有字符串长度的上限为 2020。
输出格式
若在 1010 步(包含 1010 步)以内能将 AA 变换为 BB ,则输出最少的变换步数;否则输出 NO ANSWER!。
输入样例:
输出样例:
3
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <queue>
using namespace std;
const int N = 6;
int n;
string a[N], b[N];
int extend(queue<string> &q, unordered_map<string, int> &da, unordered_map<string, int> &db, string a[], string b[]) {
string t = q.front();
q.pop();
if (db.count(t)) return da[t] + db[t]; //如果相等直接返回
for (int i = 0; i < t.size(); ++i)
for (int j = 0; j < n; ++j) {
//说明可以转换
if (t.substr(i, a[j].size()) == a[j]) {
string state = t.substr(0, i) + b[j] + t.substr(i+a[j].size());
//如果在db中找到说明就搜索到了,返回步数
if (db.count(state)) return da[t] + 1 + db[state];
//如果da中找到说明是重复添加,continue
if (da.count(state)) continue;
//否则加入da,加入队列
da[state] = da[t] + 1;
q.push(state);
}
}
return 11;
}
int bfs(string A, string B) {
queue<string> qa, qb;
unordered_map<string, int> da, db; //记录扩展的字符串到起点和终点的距离
qa.push(A), da[A] = 0;
qb.push(B), db[B] = 0;
while (qa.size() && qb.size()) {
int t = 0;
//选择队列小的扩展
if (qa.size() <= qb.size()) t = extend(qa, da, db, a, b);
else t = extend(qb, db, da, b, a);
if (t <= 10) return t;
}
return 11;
}
int main() {
string A, B;
cin >> A >> B;
while (cin >> a[n] >> b[n]) n ++;
int step = bfs(A, B);
if (step > 10) printf("%s\n","NO ANSWER!");
else printf("%d\n",step);
return 0;
}