65. [NOIP2002] 字串变换
★★ 输入文件:
string.in
输出文件:string.out
简单对比
时间限制: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
依然是大力暴搜...
单向 $BFS$ 的话开一个队列, 先把原串怼进去, 然后每次取队首字符串并尝试应用变换规则. 每应用成功一个变换后将变换后的字符串再怼回队列里. 一直重复直至变换得到待求串或者队列为空. 如果队列为空则说明不存在解. 用 $STL$ 里的 $std::string,std::pair,std::map$ 食用即可.
双向 $BFS$ 的话就从两端对称搜索, 但是深度限制在 $10$ 以内可能并不会显得多快OwO...
附双向 $BFS$ 的参考实现:
GitHub
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <cstdlib> 8 #include <iostream> 9 #include <algorithm> 10 11 typedef std::pair<std::string,int> pr; 12 13 int n; 14 int m; 15 int ans; 16 std::string from,to; 17 std::queue<pr> q1,q2; 18 std::string transform[10][2]; 19 std::map<std::string,int> m1,m2; 20 std::pair<std::string,int> p1,p2; 21 22 bool Search(); 23 void Initialize(); 24 std::string Replace(std::string,int,int,std::string); 25 26 int main(){ 27 Initialize(); 28 if(Search()) 29 std::cout<<ans<<std::endl; 30 else 31 std::cout<<"NO ANSWER!"<<std::endl; 32 return 0; 33 } 34 35 bool Search(){ 36 int len,lenp; 37 while((!q1.empty())&&(!q2.empty())){ 38 p1=q1.front(); 39 len=p1.first.size(); 40 for(int i=0;i<len;i++){ 41 for(int j=0;j<m;j++){ 42 lenp=transform[j][0].size(); 43 if(i+lenp<=len&&p1.first.compare(i,lenp,transform[j][0])==0&&m1.count(Replace(p1.first,i,lenp,transform[j][1]))==0){ 44 p2.first=Replace(p1.first,i,lenp,transform[j][1]); 45 p2.second=q1.front().second+1; 46 if(p2.second>10) 47 return false; 48 m1[p2.first]=p2.second; 49 q1.push(p2); 50 if(m2.count(p2.first)){ 51 ans=p2.second+m2[p2.first]; 52 return true; 53 } 54 } 55 } 56 } 57 q1.pop(); 58 p1=q2.front(); 59 len=p1.first.size(); 60 for(int i=0;i<len;i++){ 61 for(int j=0;j<m;j++){ 62 lenp=transform[j][1].size(); 63 if(i+lenp<=len&&p1.first.compare(i,lenp,transform[j][1])==0&&m2.count(Replace(p1.first,i,lenp,transform[j][0]))==0){ 64 p2.first=Replace(p1.first,i,lenp,transform[j][0]); 65 p2.second=q2.front().second+1; 66 if(p2.second>10) 67 return false; 68 m2[p2.first]=p2.second; 69 q2.push(p2); 70 if(m1.count(p2.first)){ 71 ans=p2.second+m1[p2.first]; 72 return true; 73 } 74 } 75 } 76 } 77 q2.pop(); 78 } 79 return false; 80 } 81 82 void Initialize(){ 83 std::ios::sync_with_stdio(false); 84 std::cin.tie(0); 85 std::cin>>from>>to; 86 while(std::cin>>transform[m][0]>>transform[m][1]) 87 m++; 88 m1[from]=0; 89 m2[to]=0; 90 q1.push(std::make_pair(from,0)); 91 q2.push(std::make_pair(to,0)); 92 } 93 94 inline std::string Replace(std::string s, int pos,int len,std::string p){ 95 return s.replace(pos,len,p); 96 }