题目地址:
https://www.luogu.com.cn/problem/P1032
题目描述:
已知有两个字串
A
,
B
A,B
A,B及一组字串变换的规则(至多
6
6
6个规则):
A
1
→
B
1
A_1\to B_1
A1→B1
A
2
→
B
2
A_2\to B_2
A2→B2
规则的含义为:在
A
A
A中的子串
A
1
A_1
A1可以变换为
B
1
B_1
B1,
A
2
A_2
A2可以变换为
B
2
B_2
B2等等。
例如:
A
=
abcd
A=\text{abcd}
A=abcd,
B
=
xyz
B=\text{xyz}
B=xyz,变换规则为:
abc
→
xu
\text{abc}\rightarrow\text{xu}
abc→xu,
ud
→
y
\text{ud}\rightarrow\text{y}
ud→y,
y
→
yz
\text{y}\rightarrow\text{yz}
y→yz
则此时,
A
A
A可以经过一系列的变换变为
B
B
B,其变换的过程为:
abcd
→
xud
→
xy
→
xyz
\text{abcd}\rightarrow\text{xud}\rightarrow\text{xy}\rightarrow\text{xyz}
abcd→xud→xy→xyz。
共进行了
3
3
3次变换,使得
A
A
A变换为
B
B
B。
输入格式:
A B
A_1 B_1
A_2 B_2
从第二行开始都是变换规则,所有字符串长度的上限为
20
20
20。
输出格式:
若在
10
10
10步(包含
10
10
10步)以内能将
A
A
A变换为
B
B
B,则输出最少的变换步数;否则输出NO ANSWER!
可以用双向BFS来做,可以节省时间和空间。以下写法采用的是分层遍历的方法。代码如下:
#include <iostream>
#include <queue>
#include <unordered_set>
using namespace std;
const int N = 6;
string a[N], b[N];
int n;
bool one_step(queue<string> &qa, unordered_set<string> &sa, unordered_set<string> &sb, string a[], string b[]) {
// 因为是分层遍历,所以要将当前队列中每个点都做扩展
for (int sz = qa.size(); sz; sz--) {
string s = qa.front(); qa.pop();
// 枚举替换位置
for (int i = 0; i < s.size(); i++)
// 枚举替换规则
for (int j = 0; j < n; j++)
if (i + a[j].size() <= s.size() && s.substr(i, a[j].size()) == a[j]) {
string ne = s.substr(0, i) + b[j] + s.substr(i + a[j].size());
if (sb.count(ne)) return true;
if (sa.count(ne)) continue;
sa.insert(ne);
qa.push(ne);
}
}
return false;
}
int bfs(string &A, string &B) {
if (A == B) return 0;
queue<string> qa, qb;
unordered_set<string> visa, visb;
qa.push(A);
visa.insert(A);
qb.push(B);
visb.insert(B);
int step = 0;
while (qa.size() && qb.size()) {
step++;
if (step > 10) break;
if (qa.size() <= qb.size()) {
if (one_step(qa, visa, visb, a, b)) return step;
} else if (one_step(qb, visb, visa, b, a)) return step;
}
return 11;
}
int main() {
string A, B;
cin >> A >> B;
while (cin >> a[n] >> b[n]) {
n++;
if (n == 6) break;
}
int step = bfs(A, B);
if (step > 10) puts("NO ANSWER!");
else printf("%d\n", step);
return 0;
}
时空复杂度与具体输入有关。