NOIP2002 字串变换题解(双向搜索)
Posted Hzoi_joker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2002 字串变换题解(双向搜索)相关的知识,希望对你有一定的参考价值。
65. [NOIP2002] 字串变换
时间限制:1 s 内存限制:128 MB
[问题描述]
已知有两个字串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!"
[输入样例]
abcd xyz abc xu ud y y yz
[输出样例]
3
在这里膜拜一下wq大佬,强行bfs藐视数据,我就比较惨了,打了好几次,正着搜反着搜都会T某个点,这就比较尴尬了,于是乎,我们引进了双向搜索这个概念。
我们可以把宽搜想像为一棵树,为了方便计算,我们暂定它为二叉树好了,如果我要搜10层,我单项搜索,会有2047个节点,但如果我双向搜索,就只有63+63==126个节点了,由此可见,双向可以说是完爆单向的,何况这只是二叉树。
于是这道题在双向搜索的前提下就无比简单了,我们把A,B分别塞进两个队列,同时广搜,直到两者相遇。至于修改操作吗,string就可以搞定了。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<string> 9 #include<cmath> 10 using namespace std; 11 string a,b; 12 string A[10],B[10]; 13 struct st{ 14 string x; 15 int js; 16 }; 17 int js; 18 queue<st> q1; 19 bool yx; 20 int p=12345,q=10000007; 21 unsigned long long xp[50]; 22 int fw[2][10000007]; 23 bool get_hash(st x,int be){ 24 unsigned long long has=0; 25 for(int i=x.x.length()-1;i>=0;i--) 26 { 27 has=has*p+int(x.x[i]); 28 } 29 has%=q; 30 if(fw[be][has]) 31 return 1; 32 fw[be][has]=x.js; 33 if(fw[be^1][has]) 34 { 35 printf("%d\n",x.js+fw[be^1][has]); 36 exit(0); 37 } 38 return 0; 39 } 40 queue<st> q2; 41 void bfs(){ 42 while(!q1.empty()&&!q2.empty()) 43 { 44 st aa=q1.front(); 45 q1.pop(); 46 if(aa.js>6) 47 { 48 yx=1; 49 printf("NO ANSWER!\n"); 50 return; 51 } 52 for(int i=1;i<=js;i++) 53 { 54 int la=-1; 55 for(int j=0;j<=aa.x.length();j++) 56 { 57 long long t=aa.x.find(A[i],j); 58 if(t>=0&&t<=20&&t!=la) 59 { 60 la=t; 61 j=la-1; 62 st c; 63 c.x=aa.x; 64 c.x.replace(t,A[i].length(),B[i]); 65 c.js=aa.js+1; 66 if(c.x.length()<=20&&!get_hash(c,0)&&c.js<=10) 67 { 68 q1.push(c); 69 } 70 } 71 } 72 } 73 st bb=q2.front(); 74 q2.pop(); 75 if(bb.js>6) 76 { 77 yx=1; 78 printf("NO ANSWER!\n"); 79 return; 80 } 81 for(int i=1;i<=js;i++) 82 { 83 int la=-1; 84 for(int j=0;j<=bb.x.length();j++) 85 { 86 long long t=bb.x.find(B[i],j); 87 if(t>=0&&t<=20&&t!=la) 88 { 89 la=t; 90 j=la-1; 91 st c; 92 c.x=bb.x; 93 c.x.replace(t,B[i].length(),A[i]); 94 c.js=bb.js+1; 95 if(c.x.length()<=20&&!get_hash(c,1)&&c.js<=10) 96 { 97 q2.push(c); 98 } 99 } 100 } 101 } 102 } 103 } 104 int main(){ 105 cin>>a>>b; 106 js=1; 107 while(cin>>A[js]>>B[js]) 108 { 109 js++; 110 } 111 js--; 112 st xx; 113 xx.x=a; 114 xx.js=0; 115 q1.push(xx); 116 get_hash(xx,0); 117 st yy; 118 yy.x=b; 119 yy.js=0; 120 q2.push(yy); 121 get_hash(yy,1); 122 xp[0]=1; 123 for(int i=1;i<=20;i++) 124 { 125 xp[i]=xp[i-1]*p; 126 } 127 bfs(); 128 if(!yx) 129 printf("NO ANSWER!\n"); 130 //while(1); 131 return 0; 132 }
以上是关于NOIP2002 字串变换题解(双向搜索)的主要内容,如果未能解决你的问题,请参考以下文章