已知有两个字串 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!。

输入样例:

abcd xyz abc xu ud y y yz

输出样例:

3


  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <unordered_map>
  5. #include <queue>
  6. using namespace std;
  7. const int N = 6;
  8. int n;
  9. string a[N], b[N];
  10. int extend(queue<string> &q, unordered_map<string, int> &da, unordered_map<string, int> &db, string a[], string b[]) {
  11. string t = q.front();
  12. q.pop();
  13. if (db.count(t)) return da[t] + db[t]; //如果相等直接返回
  14. for (int i = 0; i < t.size(); ++i)
  15. for (int j = 0; j < n; ++j) {
  16. //说明可以转换
  17. if (t.substr(i, a[j].size()) == a[j]) {
  18. string state = t.substr(0, i) + b[j] + t.substr(i+a[j].size());
  19. //如果在db中找到说明就搜索到了,返回步数
  20. if (db.count(state)) return da[t] + 1 + db[state];
  21. //如果da中找到说明是重复添加,continue
  22. if (da.count(state)) continue;
  23. //否则加入da,加入队列
  24. da[state] = da[t] + 1;
  25. q.push(state);
  26. }
  27. }
  28. return 11;
  29. }
  30. int bfs(string A, string B) {
  31. queue<string> qa, qb;
  32. unordered_map<string, int> da, db; //记录扩展的字符串到起点和终点的距离
  33. qa.push(A), da[A] = 0;
  34. qb.push(B), db[B] = 0;
  35. while (qa.size() && qb.size()) {
  36. int t = 0;
  37. //选择队列小的扩展
  38. if (qa.size() <= qb.size()) t = extend(qa, da, db, a, b);
  39. else t = extend(qb, db, da, b, a);
  40. if (t <= 10) return t;
  41. }
  42. return 11;
  43. }
  44. int main() {
  45. string A, B;
  46. cin >> A >> B;
  47. while (cin >> a[n] >> b[n]) n ++;
  48. int step = bfs(A, B);
  49. if (step > 10) printf("%s\n","NO ANSWER!");
  50. else printf("%d\n",step);
  51. return 0;
  52. }