1. 程式人生 > >NOIP2007/BZOJ1999 字串變換【題解】

NOIP2007/BZOJ1999 字串變換【題解】

描述

已知有兩個字串 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; }