zoukankan      html  css  js  c++  java
  • 字串变换 (2002 年NOIP全国联赛提高组)

              一道看似非常水的题

      大意 :将一个字串 经过几种变换规则变为给定的另一个子串 ,求最小操作数。

      code[vs] 传送门

      洛谷传送门

      已知有两个字串 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。

      

      思路:从前从后双向BFS 不加限制 若递归次数等于10次仍未找到答案时,输出NO ANSWER 。其他的若替换完后 从 前端BFS的串 在从后端BFS出现过,则此时递归次数乘2减一即为答案,   从后端BFS的情况同上。   具体实现,就按照题意来,依次扫描变换规则,进行替换,替换完的字串加入队列。

      双向BFS

    #include <iostream>
    #include <cstring>
    #include <map>
    #include <cstdio>
    using namespace std;
    const int Max = 1000000;
    string A, B;
    string s_change [7][2], Front[Max], Back[Max];
    int Limit = 1, head_Front = 1, tail_Front = 1, tail_Back = 1, head_Back = 1, tot = 0;
    map < string , int > Map_Front;
    map < string , int > Map_Back;
    void BFS ()
    {
        tot++;  //记录递归次数 
        string s, s_replace;  // s是  变换后的字串 ,s_replace 是当前需变换的字串 
        int head, tail;
        head = head_Front; //调整指针 
        tail = tail_Front; 
        for (int i = head; i <= tail; i++)
            for (int j = 1; j <= Limit; j++)  //变换种数 ,变为不同的替换规则 
            {
                int change_Front = 0;   
                while (change_Front != -1)   //每个字串中可以替换的字串不止一个 
                {
                    s_replace = Front [i];  //取出当前需被变换的字串 
                    change_Front = s_replace.find (s_change [j][0], change_Front );   //查找变换规则 ,change_Front是 当前规则 出现的位置 
                    if (change_Front >= 0) 
                    {
                        s = s_replace.replace (change_Front, s_change [j][0].length(), s_change [j][1]);  //进行替换, s存的是替换完的字串 
                        if (Map_Front [s] == 0)  //剪枝 ,若该字串出现过,则不进入队列 
                        {
                            if (Map_Back [s] != 0)    //如果能在中间遇到,就直接输出答案     
                            {
                                cout << tot * 2 - 1;
                                return ;
                            }
                            Front [++tail_Front] = s;  //加入队列 
                            Map_Front [s] = 1;    //标记为出现过 
                        }
                    }
                    if (change_Front != -1) change_Front += s_change[j][1].length();   //寻找下一个字串 
                }
            }
        head_Front = tail + 1;        //同上 ,不过是从后面进行BFS 
         head = head_Back;
        tail = tail_Back;
        for (int i = head; i <= tail; ++i)
            for (int j = 1; j <= Limit; ++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;
        if (tot == 10)    //以十次为限,若十次后仍未找到,则输出NO ANSWER 
        {
            cout << "NO ANSWER!";
            return;
        }
        BFS (); 
    }
    int main()
    {
        ios::sync_with_stdio (false);
        cin >> A >> B; 
        while (cin >> s_change[Limit][0] >> s_change [Limit][1]) Limit++;   
        Limit--;  // 替换的组数 
        Map_Front [A] = 1;  //用 map 记录 
        Map_Back [B] = 1;
        Front [1] = A;  //加入队列 
        Back [1] = B;  
        BFS ();
        return 0;
    }

      注意:此题属于那种看似很水,但是实现有难度的题。。

    myj 吊打我Orz,xxy 捆起来打我Orz,myl 文化课上天Orz, lrh 姿势水平敲高Orz, hkd 特别胖Orz%%%,cys 智商感人Orz,syl zz专业Orz,我没有学上, 我们未来一片光明
  • 相关阅读:
    Keepalived+LVS-DR+Nginx高可用故障切换模式
    【keepalived】CentOS7.0下安装教程
    【Linux】时间同步设置+防火墙设置+SELinux设置
    reset.css
    webpack打包出错 连续同一个命令打包 堆栈错误
    git操作
    js如何判断一个对象{}是否为空对象,没有任何属性,为空对象的几种方法
    页面样式 窗口大小
    Angular2路由 上线后页面刷新后报404错误
    React 上传进度条问题 原生js上传 input type=“file”
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6043257.html
Copyright © 2011-2022 走看看