版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84338035
思路分析:
为减小搜索树规模, 考虑同时从起始串A正向广搜和从目标串B逆向广搜, 两个搜索树每次各搜索一层, 具体实现上的细节以及需要注意的问题参见下面的AC代码:
//CH2908_字串变换
#include <iostream>
#include <cstdio>
#include <map>
#include <string>
#include <queue>
#include <algorithm>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<string, int> psi; typedef pair<string, string> pss;
const int MAX = 30, INF = 0x3f3f3f3f; const string END = "";
string A, B; pss rule[MAX]; int rcnt;//变换规则, 规则个数
queue<string> qa, qb; map<string, int> ma, mb;//qa: 从A开始的广搜队列, qb: 从B开始广搜队列
int main(){
cin >> A >> B; while(cin >> rule[++rcnt].fi) cin >> rule[rcnt].se; --rcnt;
qa.push(A), qa.push(END), ma[A] = 0, qb.push(B), qb.push(END), mb[B] = 0;
int res = INF, nowa = 0; //nowa: qa当前以完成的变换次数
while(nowa <= 6 && (qa.size() >= 2 || qb.size() >= 2)){
while(!qa.empty()){
string s = qa.front(); qa.pop();
if(s == END){
qa.push(END); break;
}
if(mb.count(s)){
res = 2 * nowa - 1; goto GOTO1;
}
int scnt = ma[s];
for(int i = 1; i <= rcnt; ++i){
string l = rule[i].fi, r = rule[i].se; int beg = 0;
while(beg < s.length()){
string ts = s; string::size_type pos = ts.find(l, beg);
if(pos == string::npos) break;
ts.replace(pos, l.length(), r), beg = pos + 1;
if(ma.count(ts)) continue;
ma[ts] = scnt + 1, qa.push(ts);
}
}
}
++nowa;
while(!qb.empty()){
string s = qb.front(); qb.pop();
if(s == END){
qb.push(END); break;
}
if(ma.count(s)){
res = 2 * (nowa - 1); goto GOTO1;
}
int scnt = mb[s];
for(int i = 1; i <= rcnt; ++i){
string l = rule[i].se, r = rule[i].fi; int beg = 0;
while(beg < s.length()){
string ts = s; string::size_type pos = ts.find(l, beg);
if(pos == string::npos) break;
ts.replace(pos, l.length(), r), beg = pos + 1;
if(mb.count(ts)) continue;
mb[ts] = scnt + 1, qb.push(ts);
}
}
}
}
GOTO1: if(res == INF) cout << "NO ANSWER!" << endl; else cout << res + 1 << endl;
}