[NOIP2002] 提高组P1032 字串变换

 

 

题目描述

已知有两个字串 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
输出样例#1:
3

 

双向BFS

由衷感叹STL大法好,c++的string虽然慢,但是解决小数据问题简直方便。

string::replace(k,L,s)  将原串中从k开始,长度为L的位置替换为串s。

string::find(s,i) 从原串中第i位开始找,返回s串第一次出现的位置的起点。

 

把string存进queue里,暴力宽搜各种变换即可。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 using namespace std;
 9 string ta[15],tb[15];
10 int n;
11 string a,b;
12 map<string,int>mp[3];
13 queue<string>q[3];
14 //queue<int>st[3];
15 int BFS(){
16     mp[1][a]=1;mp[2][b]=1;
17     q[1].push(a);q[2].push(b);
18     int i,j;
19     while(!q[1].empty() && !q[2].empty()){
20         int u;if(q[1].size()<=q[2].size())u=1;else u=2;
21         string s;
22         s=q[u].front();
23         if(u==1){
24             for(i=1;i<=n;i++){
25                 int k=0;
26                 while(s.find(ta[i],k)!=-1){
27                     k=s.find(ta[i],k);
28                     int len=ta[i].size();
29                     s.replace(k,len,tb[i]);
30                     if(mp[1][s]==0){
31                         mp[1][s]=mp[1][q[u].front()]+1;
32                         q[u].push(s);
33                     }
34                     if(mp[2][s]!=0){
35                         int tmp=mp[2][s]+mp[1][q[u].front()]-1;
36                         if(tmp<=10)return tmp;
37                     }
38                     k++;
39                     s=q[u].front();
40                 }
41             }
42         }
43         else{
44             for(i=1;i<=n;i++){
45                 int k=0;
46                 while(s.find(tb[i],k)!=-1){
47                     k=s.find(tb[i],k);
48                     int len=tb[i].size();
49                     s.replace(k,len,ta[i]);
50                     if(!mp[2][s]){
51                         mp[2][s]=mp[2][q[u].front()]+1;
52                         q[u].push(s);
53                     }
54                     if(mp[1][s]){
55                         int tmp=mp[1][s]+mp[2][q[u].front()]-1;
56                         if(tmp<=10)return tmp;
57                     }
58                     k++;
59                     s=q[u].front();
60                 }
61             }
62         }
63         q[u].pop();
64     }
65     return -1;
66 }
67 int main(){
68     cin>>a>>b;
69     int i,j;
70     while(cin>>ta[n+1]>>tb[n+1]) n++;
71     int ans=BFS();
72     if(ans==-1)printf("NO ANSWER!\n");
73     else cout<<ans<<endl;
74     return 0;
75 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/5970755.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值