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 }
?