1+ #include < algorithm>
2+ #include < climits>
3+ #include < cmath>
4+ #include < functional>
5+ #include < iostream>
6+ #include < map>
7+ #include < numeric>
8+ #include < queue>
9+ #include < set>
10+ #include < stack>
11+ #include < string>
12+ #include < unordered_map>
13+ #include < unordered_set>
14+ #include < vector>
15+
16+ using namespace std ;
17+
18+ // use DFS with memoization
19+ // time : O(A^N)
20+ // space : O(N^2)
21+ class Solution {
22+ private:
23+ unordered_map<string, vector<char >> um;
24+ unordered_map<string, bool > dp;
25+
26+ bool recursive (string& line) {
27+ int size = line.size ();
28+
29+ if (size == 1 ) return true ;
30+ if (dp.count (line)) return dp[line];
31+
32+ vector<vector<char >> ch (size - 1 );
33+
34+ for (int i = 0 ; i < size - 1 ; i++) {
35+ string key = {line[i], line[i + 1 ]};
36+
37+ for (char & c : um[key]) {
38+ ch[i].push_back (c);
39+ }
40+ }
41+
42+ unordered_set<string> us;
43+ unordered_set<string> visited;
44+
45+ queue<string> q;
46+ q.push (" " );
47+
48+ while (!q.empty ()) {
49+ string cur = q.front ();
50+ q.pop ();
51+
52+ if (cur.size () == size - 1 ) {
53+ us.insert (cur);
54+ continue ;
55+ }
56+
57+ for (char & c : ch[cur.size ()]) {
58+ string next = cur + c;
59+ if (visited.count (next)) continue ;
60+ if (next.size () >= 2 &&
61+ um.count ({next[next.size () - 2 ], next[next.size () - 1 ]}) == 0 )
62+ continue ;
63+
64+ visited.insert (next);
65+ q.push (next);
66+ }
67+ }
68+
69+ bool ret = false ;
70+ for (string next : us) {
71+ ret |= recursive (next);
72+ if (ret) break ;
73+ }
74+ return dp[line] = ret;
75+ }
76+
77+ public:
78+ bool pyramidTransition (string bottom, vector<string>& allowed) {
79+ for (string& s : allowed) {
80+ string key = {s[0 ], s[1 ]};
81+ char c = s[2 ];
82+
83+ um[key].push_back (c);
84+ }
85+
86+ return recursive (bottom);
87+ }
88+ };
89+
90+ // use DFS with memoization
91+ // time : O(A^N)
92+ // space : O(N^2)
93+ class Solution {
94+ private:
95+ unordered_map<string, vector<char >> um;
96+ unordered_map<string, bool > dp;
97+
98+ bool recursive (string& line) {
99+ int size = line.size ();
100+
101+ if (size == 1 ) return true ;
102+ if (dp.count (line)) return dp[line];
103+
104+ vector<vector<char >> ch (size - 1 );
105+
106+ for (int i = 0 ; i < size - 1 ; i++) {
107+ string key = {line[i], line[i + 1 ]};
108+
109+ for (char & c : um[key]) {
110+ ch[i].push_back (c);
111+ }
112+ }
113+
114+ unordered_set<string> us;
115+
116+ function<void (int , string&)> dfs = [&](int i, string& cur) {
117+ if (i == size - 1 ) {
118+ us.insert (cur);
119+ return ;
120+ }
121+
122+ for (char & c : ch[i]) {
123+ if (cur.size () > 0 ) {
124+ string key = {cur.back (), c};
125+ if (um.count (key) == 0 ) continue ;
126+ }
127+
128+ cur.push_back (c);
129+ dfs (i + 1 , cur);
130+ cur.pop_back ();
131+ }
132+ };
133+
134+ string cur = " " ;
135+ dfs (0 , cur);
136+
137+ bool ret = false ;
138+ for (string next : us) {
139+ ret |= recursive (next);
140+ if (ret) break ;
141+ }
142+ return dp[line] = ret;
143+ }
144+
145+ public:
146+ bool pyramidTransition (string bottom, vector<string>& allowed) {
147+ for (string& s : allowed) {
148+ string key = {s[0 ], s[1 ]};
149+ char c = s[2 ];
150+
151+ um[key].push_back (c);
152+ }
153+
154+ return recursive (bottom);
155+ }
156+ };
0 commit comments