牛客:[NOIP2002]字串变换(双向bfs)

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

已知有两个字串 A, B及一组字串变换的规则(至多6个规则):
A1 -> B1
A2 -> B2
规则的含义为:在A中的子串 A1可以变换为 B1、A2可以变换为 B2 …。
例如:A='abcd' B='xyz'
变换规则为:
‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
则此时,A 可以经过一系列的变换变为 B,其变换的过程为:
‘abcd’->‘xud’->‘xy’->‘xyz’
共进行了三次变换,使得A变换为B。

输入描述:

 

输入格式如下:

A B

A1 B1 \

A2 B2  |-> 变换规则

... ... /

所有字符串长度的上限为 20。

输出描述:

输出格式如下:
若在10步(包含 10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"

示例1

输入

复制abcd xyz abc xu ud y y yz

abcd xyz
abc xu
ud y
y yz

输出

复制3

3

做法

#include<bits/stdc++.h>
using namespace std;
string s,t,a[10],b[10];
int n;
queue<string> q1,q2;
unordered_map<string,int> mp1,mp2;
int bfs(){
    int step=0;
    q1.push(s);
    q2.push(t);
    mp1[s]=0;
    mp2[t]=0;
    while(++step<=5){ 
        while(mp1[q1.front()]==step-1){//上一层的
            string tmp=q1.front();
            q1.pop();
            
            for(int i=0;i<n;i++){
            	int pos=0;
            	while(pos<tmp.size()){
                	string ss=tmp;
                	if(ss.find(a[i],pos)==-1) break;//子串没有包含a[i]
                	ss.replace(ss.find(a[i],pos),a[i].size(),b[i]);//注意起始点
                	if(mp1.find(ss)!=mp1.end()) {
                        pos++;
                        continue;//搜过了
                    }
                	if(mp2.find(ss)!=mp2.end()) return step*2-1;//会合,当前这步不算
                	q1.push(ss);
                	mp1[ss]=step;
                	pos++;
                }
            }
        }
        
        while(mp2[q2.front()]==step-1){
            string tmp=q2.front();
            q2.pop();
            
           	for(int i=0;i<n;i++){
            	int pos=0;
            	while(pos<tmp.size()){
                	string ss=tmp;
                	if(ss.find(b[i],pos)==-1) break;
                	ss.replace(ss.find(b[i],pos),b[i].size(),a[i]);
                	if(mp2.find(ss)!=mp2.end()) {
                        pos++;
                        continue;//搜过了
                    }
                	if(mp1.find(ss)!=mp1.end()) return step*2;
                	mp2[ss]=step;
                	q2.push(ss);
                	pos++;
            	}
            }
        }
    }
    return -1;
}
int main(){
	cin>>s>>t;
	while(cin>>a[n]>>b[n]) n++;
	int ans=bfs();
	if(ans==-1) cout<<"NO ANSWER!";
    else cout<<ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值