#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;
}