题目描述
已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):
A_1A1 ->B_1B1
A_2A2 -> B_2B2
规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1,A_2A2 可以变换为 B_2B2 …。
例如:AA='abcdabcd'BB='xyzxyz'
变换规则为:
‘abcabc’->‘xuxu’‘udud’->‘yy’‘yy’->‘yzyz’
则此时,AA可以经过一系列的变换变为BB,其变换的过程为:
‘abcdabcd’->‘xudxud’->‘xyxy’->‘xyzxyz’
共进行了33次变换,使得AA变换为BB。
输入输出格式
输入格式:
输入格式如下:
AA BB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则
... ... /
所有字符串长度的上限为2020。
输出格式:
输出至屏幕。格式如下:
若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出"NO ANSWER!"
输入输出样例
输入样例#1: 复制
abcd xyz
abc xu
ud y
y yz
输出样例#1: 复制
3
基本上是爆搜,剪不剪枝好像都无所谓,因为题目也没给具体输入多少数据,所以目前只能用txt来存储测试样例进行输入了
有一个坑,如果一个主串包含不止一个子串,例如:abcAabcAabc这样就包含了三个子串,我们这时候就要分别对其replace
巧妙灵活运用replace,find函数很关键啊
code:
#include<bits/stdc++.h>
using namespace std;
struct node{string s;int t;};
string sa,sb,s1[7],s2[7];
map<string,bool> V;
int li=0,flag=0;
queue<node> Q;
node temp;
void bread()//广搜
{
Q.push((node){.s=sa,.t=0});
while(!Q.empty())
{
temp=Q.front(); Q.pop();
if(temp.s==sb)//符合条件
{
cout<<temp.t;
flag=1;
return ;
}
if(temp.t>10) return ;
for(int i=0;i<li;i++)//爆搜
{
int id=temp.s.find(s1[i],0);
while(id!=-1)//可能一个主串包含多个子串
{
string ts=temp.s;
ts.replace(id,s1[i].length(),s2[i]);
if(V[ts]==0)//如果这个字符串没有出现过
Q.push((node){.s=ts,temp.t+1}), V[ts]=1;
id=temp.s.find(s1[i],id+1);//往后查找
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
cin>>sa>>sb;
while(cin>>s1[li]>>s2[li]) li++;
bread();
if(flag==0) cout<<"NO ANSWER!";
return 0;
}