This solution gets "Wrong answer" result inhttp://www.programming-challenges.com/,
but it gets "Accepted" result inhttp://uva.onlinejudge.org/.
According to the explanation in http://www.programming-challenges.com/problems_specific.txt, I think my program should be correct, and it is the problem of http://www.programming-challenges.com/to judge my program as "Wrong answer".
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
using namespace std;
#define MAX_LEN 16
class Dictionary
{
private:
struct StringPtr
{
StringPtr(string* pStr) : m_pStr(pStr) {}
StringPtr(const string* pStr) : m_pStr(const_cast<string*>(pStr)) {}
bool operator == (const StringPtr& other) const
{
return (strcmp(m_pStr->c_str(), other.m_pStr->c_str()) == 0);
}
bool operator > (const StringPtr& other) const
{
return (strcmp(m_pStr->c_str(), other.m_pStr->c_str()) > 0);
}
bool operator < (const StringPtr& other) const
{
return (strcmp(m_pStr->c_str(), other.m_pStr->c_str()) < 0);
}
bool operator >= (const StringPtr& other) const
{
return !(operator<(other));
}
bool operator <= (const StringPtr& other) const
{
return !(operator>(other));
}
string* m_pStr;
};
struct WordListNode
{
WordListNode(int prev, int current) : m_prevIndex(prev), m_currentIndex(current) {}
int m_prevIndex;
int m_currentIndex;
};
typedef map<StringPtr, size_t> WordsGroup;
typedef map<StringPtr, size_t>::iterator WordsGroupIter;
typedef int** RelationGraph;
public:
Dictionary()
{
for (size_t i = 1; i <= MAX_LEN; ++i)
m_Graphs[i] = NULL;
}
~Dictionary()
{
for (size_t i = 1; i <= MAX_LEN; ++i)
{
size_t cnt = m_wordsVecs[i].size();
for (size_t j = 0; j < cnt; ++j)
{
if (m_Graphs[i])
delete[] m_Graphs[i][j];
delete m_wordsVecs[i][j];
}
if (m_Graphs[i])
delete m_Graphs[i];
}
}
void AddWord(char* word, int len)
{
string* pStr = new string(word);
m_wordsVecs[len].push_back(pStr);
m_dict[len].insert(pair<StringPtr, size_t>(StringPtr(pStr), m_wordsVecs[len].size() - 1));
}
void OutputPath(const string& strSrc, const string& strDest)
{
if (!GetConvertPath(strSrc, strDest))
{
cout << "No solution." << endl;
return;
}
}
private:
void ConstructGraph(int len)
{
if (m_Graphs[len])
return;
// Allocate Memory
size_t cnt = m_wordsVecs[len].size();
m_Graphs[len] = new int*[cnt];
for (size_t i = 0; i < cnt; ++i)
{
m_Graphs[len][i] = new int[cnt];
for (size_t j = 0; j < cnt; ++j)
m_Graphs[len][i][j] = -1;
}
// Init
for (size_t i = 0; i < cnt; ++i)
{
for (size_t j = 0; j < cnt; ++j)
{
if (m_Graphs[len][i][j] >= 0)
continue;
if (i == j)
continue;
int value = AreDoublets(m_wordsVecs[len][i], m_wordsVecs[len][j]) ? 1 : 0;
m_Graphs[len][i][j] = m_Graphs[len][j][i] = value;
}
}
}
bool GetConvertPath(const string& strSrc, const string& strDest)
{
int len = strSrc.length();
if (len != strDest.length())
return false;
if ((len <= 0) || (len > MAX_LEN))
return false;
StringPtr src(&strSrc), dest(&strDest);
bool result = GetConvertPath(src, dest, len);
return result;
}
bool GetConvertPath(const StringPtr& src, const StringPtr& dest, int len)
{
WordsGroupIter iterSrc = m_dict[len].find(src);
if (iterSrc == m_dict[len].end())
return false;
if (src == dest)
return false;
WordsGroupIter iterDest = m_dict[len].find(dest);
if (iterDest == m_dict[len].end())
return false;
ConstructGraph(len);
return GetConvertPath(len, iterSrc->second, iterDest->second);
}
bool GetConvertPath(int len, int srcIndex, int destIndex)
{
int cnt = m_wordsVecs[len].size();
char* handledWords = (char*)calloc(cnt, sizeof(char));
vector<WordListNode> candidateWords;
candidateWords.push_back(WordListNode(-1, destIndex));
handledWords[destIndex] = 1;
int startIndex = 0;
bool result = false;
while(true)
{
int candidatesCnt = candidateWords.size() - startIndex;
if (candidatesCnt <= 0)
break;
for (int i = startIndex; i < (startIndex + candidatesCnt); ++i)
{
int currentCandidateWordIndex = candidateWords[i].m_currentIndex;
for (int j = 0; j < cnt; ++j)
{
if (m_Graphs[len][currentCandidateWordIndex][j] > 0)
{
if (handledWords[j])
continue;
handledWords[j] = 1;
candidateWords.push_back(WordListNode(i, j));
if (j == srcIndex)
{
result = true;
goto FINAL_STEP;
}
}
}
}
startIndex += candidatesCnt;
}
FINAL_STEP:
free(handledWords);
if (result)
{
int index = candidateWords.size() - 1;
while(index >= 0)
{
cout << m_wordsVecs[len][candidateWords[index].m_currentIndex]->c_str() << endl;
index = candidateWords[index].m_prevIndex;
}
}
return result;
}
bool AreDoublets(const string* str1, const string* str2) const
{
int diffCnt = 0;
int index = 0;
while((*str1)[index] != '\0')
{
if ((*str1)[index] != (*str2)[index])
{
++diffCnt;
if (diffCnt > 1)
return false;
}
++index;
}
return (diffCnt == 1);
}
private:
RelationGraph m_Graphs[MAX_LEN + 1];
vector<string*> m_wordsVecs[MAX_LEN + 1];
WordsGroup m_dict[MAX_LEN + 1];
};
#define MAX_BUF_SIZE 1024
static char s_buf[MAX_BUF_SIZE];
static void RunTestCases(Dictionary& dict)
{
bool firstTime = true;
while(true)
{
if (!(cin >> s_buf))
break;
string strSrc(s_buf);
if (!(cin >> s_buf))
break;
string strDest(s_buf);
if (firstTime)
firstTime = false;
else
cout << endl;
dict.OutputPath(strSrc, strDest);
}
}
static void GetDictionaryWords(Dictionary& dict)
{
while(true)
{
fgets(s_buf, MAX_BUF_SIZE, stdin);
if ((s_buf[0] == '\0') || (s_buf[0] == '\n'))
break;
int len = strlen(s_buf);
if (s_buf[len - 1] == '\n')
{
s_buf[len - 1] = '\0';
--len;
}
dict.AddWord(s_buf, len);
}
}
static void RunTest()
{
Dictionary dict;
GetDictionaryWords(dict);
RunTestCases(dict);
}
int main(int argc, char* argv[])
{
RunTest();
return 0;
}