字符串拼接路径——bfs+剪枝

原题在这里

  概述题意,给定一个字符串数组和一个target字符串,问能否用使用字符串数组中字符串最少次数拼接出target字符串,如果不能则-1。

analyse:

  很基础的想法:

      桶存遍历target,再遍历一边字符串数组,先验证是否能拼凑出同时,存入字符串数组中每一个字符串的桶存字符,以便在bfs中遍历使用桶存数组进行处理。

code:

 

复制代码
class Solution
{
    vector<int> vis, num;
    vector<vector<int>> mp;
    bool gets, out;
    vector<int> get(vector<int> x, vector<int> y)
    {
        bool pd = true;
        for (int i = 0; i < 30; ++i)
        {
            if (x[i] > 0 && y[i] > 0) //有效处理
                gets = true;
            x[i] -= y[i];
            if (x[i] > 0)
                pd = false;
        }
        if (gets && pd)
            out = true;
        return x;
    }

public:
    int minStickers(vector<string> &stickers, string target)
    {
        vis = num = vector<int>(30, 0);
        set<vector<int>> st;
        int n = stickers.size();
        mp = vector<vector<int>>(n, vector<int>(30, 0));
        for (char i : target)
        {
            vis[i - 'a'] = 1;
            ++num[i - 'a'];
        }
        for (int i = 0; i < stickers.size(); ++i)
            for (char j : stickers[i])
                vis[j - 'a'] = 0, ++mp[i][j - 'a'];
        for (int i = 0; i < 30; ++i)
            if (vis[i])
                return -1;
        queue<vector<int>> q;
        q.push(num);
        st.insert(num);
        int ans = 0;
        out = false;
        while (q.size())
        {
            int m = q.size();
            while (m--)
            {
                vector<int> now = q.front();
                q.pop();
                for (int i = 0; i < n; ++i)
                {
                    gets = false;
                    vector<int> res = get(now, mp[i]);
                    if (gets == false)
                        continue;
                    if (st.count(res) == 0)
                    {
                        q.push(res);
                        st.insert(res);
                    }
                }
            }
            ++ans;
            if (out)
                return ans;
        }
        return -1;
    }
};
TLE未AC
复制代码

 

  进阶想法:

    1.数据范围合适,那么在判断是否能拼凑出选择使用位运算来判断。

    2.预处理字符串数组中字符串,只选择有效字符。

    3.广搜选用字符串,而不是数组。

    4.基本set去重。

code:

复制代码
class Solution
{
public:
    int minStickers(vector<string> &stickers_, string target)
    {
        string start(26, 1), end(26, 1);
        unordered_set<string> st;
        int x = 0, y = 0;
        // 初始化初始状态 h
        for (char c : target)
            start[c - 'a']++, x |= (1 << (c - 'a'));
        vector<string> stickers; // 优化贴纸集合空间
        for (string s : stickers_)
        {
            string fs = "";
            for (auto &c : s)
            {
                if (x >> (c - 'a') & 1)
                    fs += c, y |= (1 << (c - 'a'));
            }
            if (!fs.empty())
                stickers.push_back(fs);
        }
        if ((x & y) < x)
            return -1; // 不可能完成时
        int res = 0;
        queue<string> q;
        q.push(start);
        st.insert(start);
        // 广搜过程
        while (!q.empty())
        {
            int len = q.size();
            res++;
            while (len--)
            {
                string now = q.front();
                q.pop();
                for (string s : stickers)
                {
                    auto temp = now;
                    for (auto &c : s)
                        if (temp[c - 'a'] > 1)
                            temp[c - 'a']--;
                    if (temp == end)
                        return res;
                    if (!st.count(temp))
                    {
                        st.insert(temp);
                        q.push(temp);
                    }
                }
            }
        }
        return -1;
    }
};
复制代码

【Over】

posted @   Renhr  阅读(69)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示