題目連接:https://www.luogu.org/problem/P1032html
已知有兩個字串A,BA,B及一組字串變換的規則(至多66個規則):ios
A_1A1 ->B_1B1數組
A_2A2 -> B_2B2測試
規則的含義爲:在 AA中的子串 A_1A1 能夠變換爲B_1B1,A_2A2 能夠變換爲 B_2B2 …。spa
例如:A=abcd
,B=xyz
,code
變換規則爲:orm
abc
→xu
,ud
→y
,y
→yz
htm
則此時,AA能夠通過一系列的變換變爲BB,其變換的過程爲:blog
abcd
→xud
→xy
→xyz
。ci
共進行了33次變換,使得AA變換爲BB。
輸入格式以下:
AA BB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 變換規則
... ... /
全部字符串長度的上限爲2020。
輸出至屏幕。格式以下:
若在1010步(包含1010步)之內能將AA變換爲BB,則輸出最少的變換步數;不然輸出"NO ANSWER!"
abcd xyz abc xu ud y y yz
3
這是一個字符串操做的BFS。和前面作過的01迷宮和馬的遍歷相比,每次變化就至關於一次移動,而變換先後的字符串就至關於迷宮中的格點。使用STL中的string類進行find和replace操做仍是至關方便的。在前面的例題中使用bool數組來描述是否遍歷過某個格點,而這裏使用一個map數組來描述是否遍歷過某個字符串操做結果。下面是代碼。
#include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <string.h> #include <map> using namespace std; struct Node { string x; int step; }; Node q[100005]; const int MAXN = 1005; int cnt = 0, step, front, rear; string n, m, a[MAXN], b[MAXN]; map<string, bool> vis; //做用等同於數組中的vis數組 int bfs() { Node now; now.x = n; now.step = 0; front = rear = 0; q[rear] = now; rear++; while(front < rear) { now = q[front++]; if(now.x == m) { cout << now.step << endl; return 0; } if(now.step > 10) { return -1; } for(int i = 0; i < cnt; i++) { string temp = now.x; int pos = temp.find(a[i]); while(pos != -1) { temp.replace(pos, a[i].length(), b[i]); //作變換 = pos if(vis[temp] == 0) { vis[temp] = true; q[rear].x = temp; q[rear].step = now.step + 1; rear++; } temp = now.x; pos = temp.find(a[i], pos + 1); // 從下一個位置查找,作一次變換 } } } return -1; } int main() { cin >> n >> m; cnt = 0; while(cin >> a[cnt] >> b[cnt]) { cnt++; } if(bfs() < 0) { cout << "NO ANSWER!" << endl; } return 0; }
程序裏面另一個須要注意的是,A字符串中可能存在多個變換的子串,咱們須要每次變換其中的一個。有一個測試例是專門卡這種狀況的:
abaaaba abcdabaa bb dd ee ff gg c