zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    Nginx配置中运行与启动的详细介绍
    php实现文件上传进度条
    C# 提取逗号分割的字符串
    【sas proc sql】out join
    【SAS NOTE】substr函数
    【sas proc sql】子查询
    【SAS NOTE】数字字符互换
    【SAS NOTE】数组
    【sas Notel】merge
    【sas sql proc】inner join or outer join
  • 原文地址:https://www.cnblogs.com/without-sugar/p/5947134.html
Copyright © 2011-2022 走看看