NOIP2007/BZOJ1999 字串變換【題解】
阿新 • • 發佈:2018-12-08
描述
已知有兩個字串 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
題目大意
已知有兩個字串s1,s2及一些字串變換的規則a[i]變換為b[i]。輸出s1變換為s2最少的變換步數。(要求a[i]是原串的子串
雙向BFS
從起始狀態、目標狀態分別開始,兩邊輪流進行,每次各擴充套件一整層。當兩邊各自有一個狀態在記錄陣列中發生重複時,就說明這兩個搜尋過程相遇了,可以合併得出起點到終點的最少步數。
思路
使用雙向BFS演算法。
建立兩個佇列q1,q2,分別從初始串s1、目標串s2開始進行BFS,兩邊輪流進行。
在每一輪中,初始串這邊找到子串a[i],替換成b[i],目標串這邊找到子串b[i],替換成a[i],使用map陣列ans1,ans2標記每次變換後的新串x。
在BFS的過程中,第一次出現某個串x既能從初始串s1變換過來,也能從目標串s2變換時,當前輪數就是最少變換步數。
程式碼
#include<bits/stdc++.h>
using namespace std;
string s1,s2,a[10],b[10],q1[1010],q2[1010];
int n=1,la[10],lb[10],head1=1,tail1,head2=1,tail2,ans;
map<string,int> ans1,ans2;
//記錄最少變換步數
void init()
{
cin>>s1>>s2;//初始串和目標串
while (cin>>a[n])//字串變換的規則
{
cin>>b[n];
la[n]=a[n].size();
lb[n]=b[n].size();
n++;
}
n--;
}
void bfs()
{
q1[++tail1]=s1;//起始狀態
q2[++tail2]=s2;//目標狀態
ans1[s1]=1;
ans2[s2]=1;
while (head1<=tail1&&head2<=tail2)
{
string k1=q1[head1++],k2=q2[head2++];//當前隊頭
if (ans1[k1]+ans2[k2]>10) return;//特判無解
for (int i=1;i<=n;++i)//列舉所有字串變換的規則
{
int now=k1.find(a[i],0);//查詢a[i]
while (now>=0)//如果能找到a[i]
{
string x=k1;
x.replace(now,la[i],b[i]);//替換成b[i]
if (!ans1[x])
{
ans1[x]=ans1[k1]+1;
q1[++tail1]=x;//進隊
}
if (ans2[x])//兩個搜尋過程相遇
{
ans=ans1[x]+ans2[x]-2;
printf("%d\n",ans);
exit(0);
}
now=k1.find(a[i],now+1);//查詢所有a[i]
}
}//同理
for (int i=1;i<=n;++i)
{
int now=k2.find(b[i],0);
while (now>=0)
{
string x=k2;
x.replace(now,lb[i],a[i]);
if (!ans2[x])
{
ans2[x]=ans2[k2]+1;
q2[++tail2]=x;
}
if (ans1[x])
{
ans=ans1[x]+ans2[x]-2;
printf("%d\n",ans);
exit(0);
}
now=k2.find(b[i],now+1);
}
}
}
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
init();
bfs();
printf("NO ANSWER!\n");
fclose(stdin);
fclose(stdout);
return 0;
}