首页 > 其他分享 >单词接龙-双向广搜

单词接龙-双向广搜

时间:2024-09-22 22:01:20浏览次数:1  
标签:std wordList cnt int 单词 接龙 双向 que

单词接龙

题目链接

LeetCode单词接龙

题意概述

  1. 字典 \(wordList\) 中从单词 \(beginWord\) 到 \(endWord\) 的 转换序列 是一个按下述规格形成的序列 \(beginWord -> s_1 -> s_2 -> ... -> s_k:\)

  2. 每一对相邻的单词只差一个字母。
    对于 \(1 <= i <= k\) 时,每个 \(si\) 都在 \(wordList\) 中。注意, \(beginWord\) 不需要在 \(wordList\) 中。

  3. \(s_k = endWord\)

  4. 给你两个单词 \(beginWord\) 和 \(endWord\) 和一个字典 \(wordList\) ,返回 从 \(beginWord\) 到 \(endWord\) 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 \(0\) 。

思路

  1. 每个单词只能向与它差异一个字母的单词转换,可以把一个单词和它能转换的单词连一条边,那么这道题就是一个最短路的问题

  2. 考虑\(bfs\),对于一单词,把它能转化的单词加入队列中(这里的能转化指的是既与该单词相差一个字母,又在wodlist中),直到遇到目标单词,根据\(bfs\)的特性,此时一定是最短路径

  3. 过程中可以使用哈希表与字符串形成映射

  4. 时间复杂度分析:

    • \(wordlist\)中有\(n\)个元素,单词长度为\(n\)
    • 考虑最坏情况:每个单词每一位都被替换过一次,每个单词有\(26\times len\)种替换的结果,假如答案是\(ans\),那么最后的时间复杂度是要大于\(O(len^{ans})\)的
  5. 代码

#include <bits/stdc++.h>

std::string begin, end;
int n = 0;
const int maxn = 1e5 + 5;
std::unordered_map<std::string, int> wordList;
std::unordered_map<std::string, int> mp;
std::unordered_map<int, std::string> st;
std::queue<int> que;
int dis[maxn];
int cnt = -1;
void bfs()
{
    que.push(++cnt);
    mp[begin] = cnt;
    st[cnt] = begin;
    dis[cnt] = 0;
    while(!que.empty())
    {
        int tmp = que.front();
        que.pop();
        std::string cur = st[tmp];
        for (int i = 0; i < (int)cur.length(); i++)
        {
            for (int j = 0; j <= 25; j++)
            {
                std::string nxt = cur;
                char ch = (char)('a' + j);
                if (ch == nxt[i]) continue;
                nxt[i] = ch;
                if (wordList[nxt] != 0 && mp[nxt] == 0)
                {
                    std::cout << nxt << '\n';
                    que.push(++cnt);
                    mp[nxt] = cnt;
                    st[cnt] = nxt;
                    dis[cnt] = dis[mp[cur]] + 1;
                    if (nxt == end)
                    {
                        std::cout << dis[cnt] + 1;
                        return;
                    }
                }
            }
        }
    }
    std::cout << 0;
}

signed main()
{
    //freopen("in.txt", "r", stdin);
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr), std::cout.tie(nullptr);
    std::cin >> begin >> end >> n;
    std::string str;
    memset(dis, -1, sizeof(dis));
    for (int i = 1; i <= n; i++)
    {
        std::cin >> str;
        wordList[str] = 1;
    }
    if (wordList[end] == 0)
    {
        std::cout << 0;
        return 0;
    }
    bfs();
    return 0;
}
  1. 优化
    • \(bfs\)搜索的节点数是以指数级增长的,所以数据一大就爆了、
    • 考虑从起点和终点开始双向搜索
    • 这样复杂度其实没有变,但是比单向搜索快了不少
  2. 优化代码
#include <bits/stdc++.h>
std::string begin, end;
const int maxn = 1e5 + 5;
std::unordered_map<std::string, int> wordList;
std::unordered_map<std::string, int> mp;
std::unordered_map<int, std::string> st;
std::queue<int> queA, queB;
int disA[maxn], disB[maxn];
int cnt = -1, n = 0;

int extend(int judge, std::queue<int> &que, int dis[])
{
    int ans = 0x7f7f7f7f;
    int len = que.size();
    for (int l = 0; l < len; l++)
    {
        int tmp = que.front();
        que.pop();
        std::string cur = st[tmp];
        for (int i = 0; i < (int)cur.length(); i++)
        {
            std::string nxt = cur;
            for (int j = 0; j < 26; j++)
            {
                char ch = (char)('a' + j);
                if (ch == nxt[i]) continue;
                nxt[i] = ch;
                if (wordList[nxt] == 0) continue;
                if (mp[nxt] == 0)
                {
                    mp[nxt] = ++cnt;
                    st[cnt] = nxt;
                    dis[cnt] = dis[mp[cur]] + 1;
                    que.push(cnt);
                    //std::cout << judge << " " << nxt << '\n';
                }
                else
                {
                    if (judge == 0 && disA[mp[nxt]] != 0) continue;
                    if (judge == 1 && disB[mp[nxt]] != 0) continue;
                    if (judge == 0 && disB[mp[nxt] != 0])
                    {
                        //std::cout << nxt << '\n';
                        ans = std::min(ans, disA[mp[cur]] + disB[mp[nxt]]);
                    }
                    if (judge == 1 && disA[mp[nxt]] != 0)
                    {
                        //std::cout << nxt << '\n';
                        ans = std::min(ans, disB[mp[cur]] + disA[mp[nxt]]);
                    }
                }
            }
        }
    }
    if (ans != 0x7f7f7f7f) return ans;
    return 0;
}

int bfs()
{
    queA.push(++cnt);
    mp[begin] = cnt, st[cnt] = begin, disA[cnt] = 1;
    queB.push(++cnt);
    mp[end] = cnt, st[cnt] = end, disB[cnt] = 1;
    while(queA.size() && queB.size())
    {
        int judge = 0, t = 0;
        if (queA.size() > queB.size()) // 搜B
        {
            judge = 1;
            t = extend(judge, queB, disB);
        }
        else // 搜A
        {
            judge = 0;
            t = extend(judge, queA, disA);
        }
        if (t != 0) return t;
    }
    return 0;
}


void solve()
{
    std::cin >> begin >> end >> n;
    std::string str;
    for (int i = 1; i <= n; i++)
    {
        std::cin >> str;
        wordList[str] = 1;
    }
    if (wordList[end] == 0)
    {
        std::cout << 0;
        return;
    }
    std::cout << bfs();
}

signed main()
{
    freopen("in.txt", "r", stdin);
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr), std::cout.tie(nullptr);
    memset(disA, 0, sizeof(disA));
    memset(disB, 0, sizeof(disB));
    solve();
    return 0; 
}

示例

输入 
hit cog 6
hot dot dog lot log cog
输出
5

标签:std,wordList,cnt,int,单词,接龙,双向,que
From: https://www.cnblogs.com/SteinsGateSg/p/18425997

相关文章

  • Linux 中实现文本中所有的单词的第一个字符大写,其余字符小写
     001、[root@PC1test]#lsa.txt[root@PC1test]#cata.txt##测试数据afdfeDETFDSSFFdefexkmxnd[root@PC1test]#cata.txt|awk'{for(i=1;i<=NF;i++){$i=toupper......
  • 免费接龙
    很久以前,在同一个星系中,我开始尝试制作freecell,作为学习angular1.3的一种方式。我已经走了这么远,然后我就被其他事情分散了注意力,就像副项目一样。我最近有一些空闲时间(我知道,我也没想到),所以我想我应该再试一次。我基本上是从头开始,因为我对angular1.3不再感兴趣,如果我需要......
  • 【智能大数据分析 | 实验一】MapReduce实验:单词计数
    【作者主页】FrancekChen【专栏介绍】⌈⌈⌈智能大数据分析⌋......
  • 58. 最后一个单词的长度
    给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例1:输入:s="HelloWorld"输出:5解释:最后一个单词是“World”,长度为5。示例2:输入:s="flymetoth......
  • Java语言程序设计基础篇_编程练习题**18.31 (替换单词)
    目录题目:**18.31(替换单词)习题思路代码示例 运行结果替换前替换后题目:**18.31(替换单词) 编写一个程序,递归地用一个新单词替换某个目录下的所有文件中出现的某个单词。从命令行如下传递参数:javaExercise18_31dirNameoldWordnewWord习题思路(读取路径方......
  • 一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention
    一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention目录一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention效果一览基本介绍程序设计参考资料效果一览基本介绍1.Matlab实现RIME-BiTCN-BiGRU-Attention霜冰算法优化双向时间卷积双向门控循环......
  • 南沙C++信奥老师解一本通题:1337:【例3-2】单词查找树
    ​【题目描述】在进行文法分析的时候,通常需要检测一个单词是否在我们的单词列表里。为了提高查找和定位的速度,通常都画出与单词列表所对应的单词查找树,其特点如下:1.根结点不包含字母,除根结点外每一个结点都仅包含一个大写英文字母;2.从根结点到某一结点,路径上经过的字母依次连起......
  • rclcpp和rclpy中的rcl是什么英文单词的缩写吗?
    问题描述:rclcpp和rclpy中的rcl是什么英文单词的缩写吗?问题解答:在ROS2中, rcl 、 rclcpp 和 rclpy 都是指代ROS2的客户端库(ClientLibraries)的不同部分,其中: rcl 是"ROSClientLibrary"的缩写,它是ROS2的核心客户端库,提供了跨语言的通用接口和功能。 rclcpp......
  • 双向广搜
    双向广搜用途一:小优化BFS的剪枝策略,分两侧展开分支,哪侧数量少就从哪侧展开用途二:特征:全量样本不允许递归完全展开,但是半量样本可以完全展开。(完全展开的过程中有可能能够进行分组,进行常数级优化)过程:把数据分成两部分,每部分各自展开计算结果,然后设计两部分结果的整合逻......
  • 计算机与网络配置管理中常见单词
    单词  rule规则Virtual虚拟Linux中/bin目录是binary二进制的缩写Linuxkernel内核linuxfirewall防火墙authenticationbinary二进制security安全module模块table表show查看state状态port端口Request请求Update更新Database数据库staticstate静......