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

  • 相关阅读:
    ##日常代码中,我们需要配的几种数据源的配置文件
    ##Sping框架IOC中常用的注解大家一定要记住
    ##事务管理器工具类
    ##管理连接的工具类 用来实现连接 和线程的绑定
    ##处理转账事务的多线程问题,让其在一个线程处理账务的增加和减少
    学习笔记——spark安装配置
    学习笔记——spark基础实验二
    学习笔记——spark实验一
    课堂测试之数据清洗
    Mapreduce实例——WordCount
  • 原文地址:https://www.cnblogs.com/zealsoft/p/11337263.html
Copyright © 2011-2022 走看看