zoukankan      html  css  js  c++  java
  • 洛谷 P1032 字串变换题解

    题目链接:https://www.luogu.org/problem/P1032

    题目描述

    已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):

    A_1A1 ->B_1B1

    A_2A2 -> B_2B2

    规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1A_2A2 可以变换为 B_2B2 …。

    例如:A=abcd,B=xyz

    变换规则为:

    abcxuudyyyz

    则此时,AA可以经过一系列的变换变为BB,其变换的过程为:

    abcdxudxyxyz

    共进行了33次变换,使得AA变换为BB。

    输入格式

    输入格式如下:

    ABB
    A_1A1 B_1B1
    A_2A2 B_2B2 |-> 变换规则

    ... ... /

    所有字符串长度的上限为2020。

    输出格式

    输出至屏幕。格式如下:

    若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出"NO ANSWER!"

    输入输出样例

    输入 #1
    abcd xyz
    abc xu
    ud y
    y yz
    
    输出 #1
    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 abcdaba
    a b
    b d
    d e
    e f
    f g
    g c

  • 相关阅读:
    串口速率问题
    java中byte short int的理解
    matlab 设置坐标轴的有效数字
    Tomcat闪退
    解决linux下sudo更改文件权限报错xxxis not in the sudoers file. This incident will be reported.
    Git的常用命令
    [原创]创建指定RowState属性的DataRow实例
    [转]中文VS2008中安装ASP.NET MVC框架出现问题的解决方法
    [转]JavaScript为事件处理器传递参数
    [转]LINQ to SQL(LINQ2SQL) vs. ADO.NET Entity Framework
  • 原文地址:https://www.cnblogs.com/zealsoft/p/11337263.html
Copyright © 2011-2022 走看看