最小操作数

题目详情如下:
给定一个单词集合Dict,其中每个单词的长度都相同。现从此单词集合Dict 中抽取两个
单词A、B,我们希望通过若干次操作把单词A 变成单词B,每次操作可以改变单词的一个
字母,同时,新产生的单词必须是在给定的单词集合Dict 中。求所有行得通步数最少的修
改方法。
举个例子如下:
Given:
A = “hit”
B = “cog”
Dict = [“hot”,”dot”,”dog”,”lot”,”log”]
Return
[
[“hit”,”hot”,”dot”,”dog”,”cog”],
[“hit”,”hot”,”lot”,”log”,”cog”]
]
即把字符串A = “hit”转变成字符串B = “cog”,有以下两种可能:
“hit” -> “hot” -> “dot” -> “dog” -> “cog”;
“hit” -> “hot” -> “lot” -> “log” ->”cog”。

这一题相当的好,详细解析见编程艺术第32章

#include <iostream>
#include<vector>
#include<string>
#include<set>
#include <map>
#include <queue>
using namespace std;


class Solution
{
public:
    // help 函数负责找到所有的路径
    void help(int x,vector<int> &d, vector<string> &word,vector<vector<int> > &next,
        vector<string> &path,vector<vector<string> > &answer) {
            path.push_back(word[x]);
            if (d[x] == 0) { //已经达到终点了
                answer.push_back(path);
            }
            else {
                int i;
                for (i = 0; i <next[x].size(); ++i) {
                    help(next[x][i],d, word, next,path,answer);
                }
            }
            path.pop_back(); //回溯
    }
    vector<vector<string>> findLadders(string start, string end, set<string>& dict)
    {
        vector<vector<string> > answer;
        if (start == end) { //起点终点恰好相等
            return answer;
        }
        //把起点终点加入字典的map
        dict.insert(start);
        dict.insert(end);
        set<string>::iterator dt;
        vector<string> word;
        map<string,int>allword;
        //把set 转换为map,这样每个单词都有编号了。
        for (dt = dict.begin(); dt!= dict.end(); ++dt) {
            word.push_back(*dt);
            allword.insert(make_pair(*dt, allword.size()));
        }
        //建立连边 邻接表
        vector<vector<int> > con;
        int i,j,n =word.size(),temp,len = word[0].length();
        con.resize(n);
        for (i = 0; i < n; ++i){
            for (j = 0; j <len; ++j) {
                char c;
                for (c =word[i][j] + 1; c <= 'z'; ++c) { //根据上面第二种方法的优化版的思路,让每个单词每个位置变更大
                    char last =word[i][j];
                    word[i][j] =c;
                    map<string,int>::iterator t = allword.find(word[i]);
                    if (t !=allword.end()) {
                        con[i].push_back(t->second);
                        con[t->second].push_back(i);
                    }
                    word[i][j] =last;
                }
            }
        }
        //以下是标准bfs 过程
        queue<int> q;
        vector<int> d;
        d.resize(n, -1);
        int from = allword[start],to = allword[end];
        d[to] = 0; //d 记录的是路径长度,-1 表示没经过
        q.push(to);
        vector<vector<int> > next;
        next.resize(n);
        while (!q.empty()) {
            int x = q.front(), now= d[x] + 1;
            //now 相当于路径长度
            //当now > d[from]时,则表示所有解都找到了
            if ((d[from] >= 0)&& (now > d[from])) {
                break;
            }
            q.pop();
            for (i = 0; i <con[x].size(); ++i) {
                int y = con[x][i];
                //第一次经过y
                if (d[y] < 0) {
                    d[y] = now;
                    q.push(y);
                    /************************************************************************/
                    /*反着bfs搜索,所以next[y].push_back(x);注意BFS求得就是最短路径
                    /************************************************************************/
                    next[y].push_back(x);
                }
                //非第一次经过y
                else if(d[y] ==now) { //是从上一层经过的,所以要保存
                    next[y].push_back(x);
                }
            }
        }

        if (d[from] >= 0) { //有解
            vector<string>path;
            help(from, d,word,next, path,answer);
        }

        return answer;

    }
};



int main(){

    set<string> dict;
    dict.insert("hot");
    dict.insert("dot");
    dict.insert("dog");
    dict.insert("lot");
    dict.insert("log");

    Solution a;

    vector<vector<string>> ans = a.findLadders("hit","cog",dict);

    for(int i=0;i<ans.size();i++){
        for(int j=0;j<ans[i].size();j++){
            cout<<ans[i][j]<<" ";
        }
        cout<<endl;
    }

    system("pause");
    return 0;
}

这段代码看了一个晚上和半个上午,可以说大致懂了,还有两处不是很清楚
1.else if(d[y] ==now) { //是从上一层经过的,所以要保存
next[y].push_back(x);
}

2.help()这个递归函数

究其原因还是对BFS和DFS理解不深入,打算过几天深入做几个相关的题再回头看这题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ac*sin(2*pi*fc*t); %载波 y = (2*s-1).*c; %2PSK调制好的,根据你的要求,我会为你提供解答。这是一道经典的字符串编辑问题信号 SNR = -10:1:20; %信噪比范围 BER = zeros(size(SNR)); %误,可以使用动态规划算法来解决。 具体来说,我们可以定义一个二维数组dp,其中dp码率 for i=1:length(SNR) n = sqrt(0.5*10^(-SNR(i)/10))*([i][j]表示将a的前i个字符变成b的前j个字符所需的最少操作数。 接randn(1,length(y))); %高斯白噪声 r = y+n; %加入噪声的信号 下来,我们可以考虑dp数组的初始化。当i或j为0时,对应的dp[i][j]就 b = (r>0); %阈值判决 BER(i) = sum(abs(s-b))/length(s); %误是另一个字符串的长度,因为此时我们只需要添加或删除对应数量的字符即可。 然后,我们码率 end figure(3); semilogy(SNR,BER); title('2PSK抗噪声性能分析'); 可以考虑状态转移方程。如果a[i-1]等于b[j-1],那么dp[i][jxlabel('SNR(dB)'); ylabel('BER'); ``` 4. 4PSK抗噪声性能分析 ```mat]就等于dp[i-1][j-1],因为此时不需要进行任何操作。如果a[i-lab % 4PSK抗噪声性能分析 fs = 10000; %采样频率 Ts =1]不等于b[j-1],那么我们可以进行三种操作中的一种: 1. 将a的 1/fs; %采样周期 T = 1; %信号时间长度 t = 0:Ts:T第i个字符替换为b的第j个字符,此时dp[i][j]就等于dp[i-1][-Ts; %时间序列 s = randi([0,3],1,length(t)); %随机四进制序列j-1]+1。 2. 删除a的第i个字符,此时dp[i][j]就等于dp[i- Ac = 1; %载波幅度 fc = 1000; %载波频率 c = Ac1][j]+1。 3. 在a的第i个字符后面插入b的第j个字符,此时dp*sin(2*pi*fc*t); %载波 y1 = Ac*sin(2*pi*fc*t+pi/4); %[i][j]就等于dp[i][j-1]+1。 最终,dp[a.length()][b.length()]就是将a变成b所需的最少操作数。 希望这个解答能够帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值