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.
pro:给一个start的string和一个end的string,求start变化到end的所有最短路径,每一步只能变化一个字母,中间的字符串必须在dict中
sol:bfs,对于一个单词,其每一位能替换成其他的25位,依据这个bfs,最先找到了之后就是最小的步数,但这一层还是要做完以便找到所有的最短路径。
skill:之前一直超时,有两个需要注意的地方能优化,
第一,从end找start,因为记录前驱节点在bfs比较容易,这样就能
第二,先将dict加上start加上end预处理,每个单词能够一步转化到的其他单词,存在一个邻接表中,bfs时快很多
code:
class Solution
{
public:
void init(string start,string end,unordered_set<string> &dict,vector< vector<string> > &dictvec,map<string,int> &dictindex,map<int,string> &dictvalue)//预处理dict,保存一个邻接表
{
dictindex.clear(),dictvalue.clear();
dictvec.clear();
unordered_set<string>::iterator it;
int cnt=0;
for(it = dict.begin();it!=dict.end();it++)
{
dictindex[*it] = cnt;
dictvalue[cnt++] = *it;
}
if(dict.find(start)==dict.end())
{
dictindex[start] = cnt;
dictvalue[cnt++] = start;
}
if(dict.find(end)==dict.end())
{
dictindex[end] = cnt;
dictvalue[cnt++] = end;
}
int i,j,k;
string front,temp;
char ch;
vector<string> tt;
tt.clear();
for(i=0;i<cnt;i++)
{
tt.clear();
front = dictvalue[i];
temp = front;
for(j=0;j<front.length();j++)
{
for(k=0;k<26;k++)
{
ch='a'+k;
if(ch!=front[j])
{
temp[j] = ch;
if(dict.find(temp)!=dict.end()||temp==start||temp==end)
{
tt.push_back((temp));
}
}
}
temp[j] = front[j];
}
dictvec.push_back(tt);
}
}
vector< vector<string> > findLadders(string start,string end,unordered_set<string> &dict)
{
string sss;
sss=start;
start=end;
end=sss;
vector< vector<string> > dictvec;
map<string,int> dictindex;
map<int,string> dictvalue;
init(start,end,dict,dictvec,dictindex,dictvalue);
vector< vector<string> >myvec;
myvec.clear();
if(start==end)//father记录的是从后往前的,因此end找到start
{
myvec.push_back(vector<string>(2,start));
return myvec;
}
int i,j,k,step;
char ch;
string temp_string,front_string;
//set<string> myset;
map<string,int> mymap;
mymap.clear();
int front_step,front_father,temp_step,temp_father;
vector<string> string_vec;
vector<int> step_vec;
vector< vector<int> > father_vec;
string_vec.clear(),step_vec.clear(),father_vec.clear();
int front,rear;
front=rear=0;
string_vec.push_back(start),step_vec.push_back(1),father_vec.push_back(vector<int>(1,-1));
rear++;
mymap[start]=0;
bool flag=false;
int res;
int end_index=-1;
int end_step=0;
while(front<rear)
{
front_string = string_vec[front];
int front_index = dictindex[front_string];
//cout<<"&&&"<<front<<' '<<front_string<<endl;
front_step = step_vec[front++];
if(end_index!=-1&&front_step>end_step)
break;
for(i=0;i<dictvec[front_index].size();i++)
{
temp_string = dictvec[front_index][i];
if((dict.find(temp_string)!=dict.end()||temp_string==end)&&mymap.find(temp_string)!=mymap.end())
{
int index=mymap[temp_string];
if(step_vec[index]==front_step+1)
{
father_vec[index].push_back(front-1);
}
}
if (mymap.find(temp_string)==mymap.end()&&(dict.find(temp_string)!=dict.end()||temp_string==end))
{
if(temp_string==end)
{
end_index=rear;
end_step=front_step+1;
}
mymap[temp_string]=rear;
string_vec.push_back(temp_string);
step_vec.push_back(front_step+1);
father_vec.push_back(vector<int>(1,front-1));
rear++;
}
}
}
if(end_index==-1) return myvec;
vector<string> temp;
temp.clear();
temp.push_back(end);
dfs(myvec,end_index,string_vec,father_vec,temp);
//test(father_vec);
return myvec;
}
void dfs(vector< vector<string> > &res,int myfather,vector<string> &string_vec,vector< vector<int> > &father_vec,vector<string> &temp)
{
string tt;
int i,j;
if(myfather==-1)
{
temp.pop_back();
res.push_back(temp);
temp.push_back("hi");
}
else
{
for(i=0;i<father_vec[myfather].size();i++)
{
int index=father_vec[myfather][i];
if(index!=-1)
temp.push_back(string_vec[index]);
else temp.push_back("hi");
dfs(res,father_vec[myfather][i],string_vec,father_vec,temp);
temp.pop_back();
}
}
}
};