Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the dictionary
For example,
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
Note:
- All words have the same length.
- All words contain only lowercase alphabetic characters.
/*2015.9.1cyq*/
#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <unordered_map>
using namespace std;
class Solution {
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> result;
unordered_set<string> cur,next;//当前层和下一层
unordered_set<string> visited;
unordered_map<string,vector<string>> preNode;
bool found=false;
cur.insert(start);
while(!cur.empty()&&!found){
for(auto it=cur.begin();it!=cur.end();it++)
visited.insert(*it);//本层结点全设置为访问过
for(auto it=cur.begin();it!=cur.end();it++){
vector<string> newWords=nextWords(*it,end,dict,visited);
for(auto ik=newWords.begin();ik!=newWords.end();++ik){
if(*ik==end) found=true;
next.insert(*ik);//通过多种路径到达新结点时会自动去重
preNode[*ik].push_back(*it);//记录前驱结点
}
}
cur.clear();
swap(cur,next);
}
if(found){
vector<string> path;
dfs(preNode,start,end,path,result);
}
return result;
}
private:
//利用前驱map,从end向start,dfs出所有路径
void dfs(unordered_map<string,vector<string>> &preNode,string &start,string &word,
vector<string> &path,vector<vector<string>> &result){
path.push_back(word);
if(word==start){
result.push_back(path);
reverse(result.back().begin(),result.back().end());
}else{
for(auto it=preNode[word].begin();it!=preNode[word].end();++it)
dfs(preNode,start,*it,path,result);
}
path.pop_back();
}
//获取与s相差一个字符的字符串,要求该字符串未被访问过
//注意找到新字符串后,先不标记为访问过,因为可能通过多种路径找到新字符串,所有路径都要输出
vector<string> nextWords(const string &s,const string &target,unordered_set<string> &dict,
unordered_set<string> &visited){
vector<string> result;
for(int i=0;i<s.size();i++){
string tmp(s);
for(char c='a';c<='z';c++){
if(tmp[i]==c) continue;
swap(c,tmp[i]);
if((dict.find(tmp)!=dict.end()||tmp==target)&&visited.find(tmp)==visited.end())
result.push_back(tmp);
swap(c,tmp[i]);
}
}
return result;
}
};
int main(){
string start="hit";
string end="cog";
string a[]={"hot","dot","dog","lot","log"};
int n=sizeof(a)/sizeof(string);
unordered_set<string> dict;
for(int i=0;i<n;i++)
dict.insert(a[i]);
Solution solu;
vector<vector<string>> ret=solu.findLadders(start,end,dict);
for(auto it=ret.begin();it!=ret.end();++it){
for(auto ik=(*it).begin();ik!=(*it).end();++ik)
cout<<*ik<<" ";
cout<<endl;
}
return 0;
}