[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;
}
原文地址:https://www.cnblogs.com/without-sugar/p/5947134.html