Word Ladder II

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

  1. Only one letter can be changed at a time
  2. 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.
struct Node
{
    int vindex;
    int path;
    int previous;
};
class Solution {
public:
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) 
    {
        vector<vector<string>> result;
        int len=start.length();

        vector<string> vdict;
        map<string,int> ids;
        vdict.push_back(start);
        ids[start]=0;
        for(unordered_set<string>::iterator it=dict.begin();it!=dict.end();it++)
        {
            ids[*it]=vdict.size();
            vdict.push_back(*it);            
        }
        vdict.push_back(end);
        ids[end]=vdict.size()-1;

        dict.insert(start);
        dict.insert(end);

        vector<vector<int>>adj;
        for(int i=0;i<vdict.size();i++)
        {
            vector<int> adj0;
            string str=vdict[i];
            for(int j=0;j<len;j++)
            {
                for(char c='a';c<='z';c++)
                    if(vdict[i][j]!=c)
                    {
                        str[j]=c;
                        if(dict.count(str)) adj0.push_back(ids[str]);                        
                    }
                str[j]=vdict[i][j];
            }
            adj.push_back(adj0);
        }                                
        
        vector<Node*> path;        
        Node* newnode=new Node();
        newnode->vindex=ids[start];
        newnode->path=1;
        newnode->previous=-1;
        path.push_back(newnode);                                    

        int index=0;
        int minpath=0;        
        int oldpath=0;

        while(index<path.size())
        {            
            if(path[index]->path>oldpath)
            {
                oldpath=path[index]->path;
                int i=index;
                while(i<path.size())
                {                    
                    unordered_set<string>::iterator it= dict.find(vdict[path[i]->vindex]);
                    if(it!=dict.end()) dict.erase(it);
                    i++;
                }                
            }
            if(minpath>0 && path[index]->path==minpath)
                break;                
            // a path found
            if(path[index]->vindex==vdict.size()-1)
                minpath=path[index]->path;
            //next word
            for(int i=0;i<adj[path[index]->vindex].size();i++)
            {                   
                if(dict.count(vdict[adj[path[index]->vindex][i]]))
                {                            
                        newnode=new Node();
                        newnode->path=oldpath+1;
                        newnode->vindex=adj[path[index]->vindex][i];
                        newnode->previous=index;
                        path.push_back(newnode);
                }                        
            }
            index++;
        }

        for(int i=0;i<path.size();i++)
        if(path[i]->path==minpath && vdict[path[i]->vindex]==end)
        {
            vector<string> words;
            int index=i;
            do
            {
                words.insert(words.begin(),vdict[path[index]->vindex]);
                index=path[index]->previous;
            }
            while(index!=-1);
            result.push_back(words);
        }
        
        return result;
    }    
};

 

posted @ 2014-05-30 01:20  erictanghu  阅读(108)  评论(0编辑  收藏  举报