版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/88981915
题目描述
描述
已知有两个字串 AA,BB 及一组字串变换的规则(至多6个规则):
·A1 -> B1
·A2 -> B2
规则的含义为:在 AA中的子串 A1A1 可以变换为 B1B1、A2A2 可以变换为 B2B2 …。
例如:A=’abcd’ B=’xyz’
变换规则为:
‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
则此时,AA 可以经过一系列的变换变为 BB,其变换的过程为:
‘abcd’->‘xud’->‘xy’->‘xyz’
共进行了三次变换,使得 AA 变换为BB。
题目大意
有若干个方案,例如A→B,就会使得串S中的字串A替换为B;问至少替换多少次,才能将起始串串成目标串。
题解
这一道题我们采取双向广搜的方法,从起点和终点同时扩展,且将扩展次数控制在5步以内;如果中间状态冲突,说明搜索到了,我们直接输出两个步骤之和即可。
而双向广搜的大致模板就是:
for step=1 → MAX
bfs1:拓展一层
bfs2:拓展一层
代码如下:
#include <bits/stdc++.h>
using namespace std;
struct node
{
string s;
int v;
};
int n=1;
string A,B;
string a[100],b[100];
queue< node >q1,q2;
map < string, int> vis1,vis2;
int S(string s)
{
return s.size();
}
int main(void)
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
cin>>A>>B;
while (cin>>a[n]>>b[n])
{
if (a[n]=="0") break;
n ++;
}
n --;
if (A==B) return puts("0"),0;
vis1[A]=vis2[B]=1;
q1.push(node{A,0});
q2.push(node{B,0});
for (int step=1;step<=5;++step)
{
int now1=q1.front().v;
int now2=q2.front().v;
while (q1.size() && q1.front().v==now1)
{
int num1=q1.front().v;
string top1=q1.front().s;
q1.pop();
for (int i=1;i<=n;++i)
for (int j=0;j<=S(top1)-S(a[i]);++j)
if (a[i]==top1.substr(j,S(a[i])))
{
string Next;
Next=top1;
Next.replace(j,S(a[i]),b[i]);
if (vis1[Next]) continue;
if (vis2[Next]) return cout<<(step+vis2[Next]),0;
vis1[Next]=num1+1;
q1.push(node{Next,num1+1});
}
}
//正向匹配
while (q2.size() && q2.front().v==now2)
{
int num2=q2.front().v;
string top2=q2.front().s;
q2.pop();
for (int i=1;i<=n;++i)
for (int j=0;j<=S(top2)-S(b[i]);++j)
if (b[i]==top2.substr(j,S(b[i])))
{
string Next;
Next=top2;
Next.replace(j,S(b[i]),a[i]);
if (vis2[Next]) continue;
if (vis1[Next]) return cout<<(step+vis1[Next]),0;
vis2[Next]=num2+1;
q2.push(node{Next,num2+1});
}
}
//反向匹配
}
puts("NO ANSWER!");
return 0;
}