#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <unordered_set>
class Solution {
public:
struct Node
{
string s;
int end;// the last letter index in the s;
vector<Node *> vct;
bool isVisted;
bool isDiscovered;
void AddChild(Node *p)
{
vct.push_back(p);
}
Node()
{
isVisted = false;
isDiscovered = false;
end = 0;
}
Node *FindNextNotVisted()
{
for (std::vector<Node *>::size_type i = 0; i != vct.size(); i++)
{
if (vct[i]->isDiscovered == false)
{
//vct[i]->isVisted = true;
return vct[i];
}
}
return NULL;
}
bool isHasChild()
{
return this->vct.size() > 0 ? true : false;
}
bool isAllChildVisted()
{
if (this->isHasChild() == false)
{// if does not have child then return false;
return false;
}
for (std::vector<Node *>::size_type i = 0; i != vct.size(); i++)
{
if (vct[i]->isDiscovered == false)
{
return true;
}
}
return false;
}
};
stack<Node *> FindIt(string s, int i, unordered_set<string> &dict)
{// return the first proper node from s started from i[ ;
stack<Node *> stk;
for (int j = i; j<s.size(); ++j)
{
string tmp = string(&s[i], &s[j + 1]);
//string tmp = s.substr(i,j);
std::unordered_set<std::string>::const_iterator got = dict.find(tmp);
if (got != dict.end())
{// if find;
//stk.push();
Node *pnd = new Node;
pnd->end = j+1;
pnd->s = tmp;
stk.push(pnd);
}
}
return stk;
}
string temp;
vector<string> deepFistT(Node *pnd)
{// deep traverse the tree and get all the path
vector<string> result;
vector<Node *> stk;
stk.push_back(pnd);
Node * ptmp(0);
while (!stk.empty())
{
while (pnd)
{
ptmp = pnd;
pnd = pnd->FindNextNotVisted();
if (pnd)
{
stk.push_back(pnd);
pnd->isDiscovered = true;
}
}
// visit the whole stak from starting to ending;
//if (ptmp && ptmp->isVisted == false)
if (ptmp->isAllChildVisted() == true)
{
stk.pop_back();
}
else if (ptmp->isHasChild() == false)
{
for (std::vector<Node*>::size_type i = 0; i != stk.size(); ++i)
{
string temp2 = (stk[i]->s);
stk[i]->isVisted = true;
temp += (temp2 + " ");
stk[i]->isVisted = true;
}
result.push_back(temp);
std::cout << temp << std::endl;
temp = "";
}
//visit ends
stk.pop_back();
if (stk.size()!=0)
pnd = stk.back();
}
return result;
}
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
vector<string> vct;
if (s.size() == 0 || dict.size() == 0) return vct;
Node * phead = new Node();
std::queue<Node *> myqueue;
stack<Node *> stk = FindIt(s, 0, dict);
while (!stk.empty())
{
phead->AddChild(stk.top());
myqueue.push(stk.top());
stk.pop();
}
while (!myqueue.empty())
{
Node *pheadq = myqueue.front();
stk = FindIt(s, pheadq->end, dict);
while (!stk.empty())
{
pheadq->AddChild(stk.top());
myqueue.push(stk.top());
stk.pop();
}
myqueue.pop();
}
return deepFistT(phead);
//find nodes in the first level;and put them in the queue;
}
void testDeepWhole()
{
Node *pnd = new Node[10];
for (int i = 0; i < 10; ++i)
{
char a = i + '0';
char buffer[2] = {0};
strncpy(buffer, &a, 1);
//strcpy_s(buffer, &a);
string ss(buffer);
pnd[i].s = ss + " test ";
//pnd[i].s[1] = 0;
}
for (int i = 0; i < 5; ++i)
{
// 0 :1 2 3 4 5 ;
// 2:6 3:7 4:8 5:9;
pnd[0].AddChild(&pnd[1 + i]);
}
for (int i = 2; i <= 5; ++i)
{
pnd[i].AddChild(&pnd[i + 4]);
}
Node *pnew = new Node;
pnew->s = " p2'schildren ";
pnd[2].AddChild(pnew);
vector<string> result = this->deepFistT(pnd);
for (int i = 0; i < result.size(); ++i)
{
std::cout << result[i] << endl;
}
//(auto: a resutl)
}
};
int main()
{
string s = "catsanddog";
std::unordered_set<std::string> myset = {"cat", "cats", "and", "sand", "dog"};
Solution sl;
sl.wordBreak(s,myset);
}