[NOIP2002]字串变换
题目描述
已知有两个字串 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!"
输入输出样例
输入样例#1:
abcd xyz abc xu ud y y yz
输出样例#1:
3
双向BFS, 两个map去重。
//双向BFS, 两个Map去重判断 #include <iostream> #include <map> #include <string> #include <cstdlib> #define MAX 1000000 using namespace std; string A, B; string s_change[7][2], Front[MAX], Back[MAX];//6种变化规律, 从前往后BFS和从后往前BFS int ans = 1, head_Front = 1, tail_Front = 1, head_Back = 1, tail_Back = 1, tot = 0; //对应指针 map <string, int> Map_Front;//两个Map map <string, int> Map_Back; void bfs() { tot++;//10次就结束 string s, s_replace; int head, tail; head = head_Front; tail = tail_Front;//调整指针 for(int i = head; i <= tail; ++i) for(int j = 1; j <= ans; ++j)//变换种数 { int change_Front = 0; while(change_Front != -1)//每个单词中可以供替换的字串不一定只有一个 { s_replace = Front[i]; change_Front = s_replace.find(s_change[j][0], change_Front);// 查找 if(change_Front >= 0) { s = s_replace.replace(change_Front, s_change[j][0].length(), s_change[j][1]);//替换 if(Map_Front[s] == 0)//剪枝, 如果出现过不进入队列 { if(Map_Back[s] != 0)//如果能Meet in the Middle, 输出 { cout << tot * 2 - 1; return; } Front[++tail_Front] = s;//加入队列 Map_Front[s] = 1;//标记出现 } } if(change_Front != -1) change_Front = change_Front + s_change[j][1].length();//寻找下一个字串 } } head_Front = tail + 1; head = head_Back; tail = tail_Back;//同上 for(int i = head; i <= tail; ++i) for(int j = 1; j <= ans; ++j) { int change_Back = 0; while(change_Back != -1) { s_replace = Back[i]; change_Back = s_replace.find(s_change[j][1], change_Back); if(change_Back >= 0) { s = s_replace.replace(change_Back, s_change[j][1].length(), s_change[j][0]); if(Map_Back[s] == 0) { if(Map_Front[s] != 0) { cout << tot * 2; return; } Back[++tail_Back] = s; Map_Back[s] = 1; } } if(change_Back != -1) change_Back = change_Back + s_change[j][0].length(); } } head_Back = tail + 1; /*for(int i = head_Front; i <= tail_Front; ++i) cout << Front[i] << endl; cout << tot << endl << endl << endl; for(int i = head_Back; i <= tail_Back; ++i) cout << Back[i] << endl; system("pause"); system("CLS");*/ if(tot == 10)//10次为限 { cout << "NO ANSWER!"; return; } bfs(); } int main() { ios::sync_with_stdio(false); cin >> A >> B; while(cin >> s_change[ans][0] >> s_change[ans][1]) ans++;//输入 ans--; Map_Front[A] = 1;//Map记录 Map_Back[B] = 1; Front[1] = A;//加入队列 Back[1] = B; bfs();//开始BFS return 0; }