【习题·搜索】字串变换(双向广搜)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/Ronaldo7_ZYB/article/details/88981915