【双向广搜】 字串变换
传送门
题意
给定字符串\(A、B\),给定串\(A\)的变换规则,问能否通过10次变换内将\(A\)变成\(B\)
数据范围
\(1\leq |A|、|B|\leq 20\)
题解
两个队列分别是从起始向终点搜和反向搜索
- 每次都从当前层数少的进行扩展,实际运行下较优
- \(substr(int \;i,int\; j)\)函数表示的是从\(i\)开始长度为\(j\)的子串
- \(unordered\_map\)记录距离以及是否搜索到
Code
#include<bits/stdc++.h>
using namespace std;
#define ump unordered_map
string a[7],b[7];
int n;
int extend(queue<string>&q,ump<string,int>&dst,ump<string,int>&ded,string a[],string b[]){
// 每次扩展当前一层节点
for(int k=0,lk=q.size();k<lk;k++){
string t=q.front();
q.pop();
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 now=t.substr(0,i)+b[j]+t.substr(i+a[j].size()); // substr 只有起点时为起点到终点
if(dst.count(now)) continue; // 已经入队
if(ded.count(now)) return dst[t]+ded[now]+1;
dst[now]=dst[t]+1;
q.push(now);
}
}
}
return 11;
}
int bfs(string A,string B){
queue<string>qst,qed;
ump<string,int>dst,ded;
qst.push(A);qed.push(B);
dst[A]=0;ded[B]=0;
while(qst.size() && qed.size()){
int t;
if(qst.size()<=qed.size()) t=extend(qst,dst,ded,a,b);
else t=extend(qed,ded,dst,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) cout<<"NO ANSWER!"<<endl;
else cout<<step<<endl;
return 0;
}