21 #ifndef FST_DFS_VISIT_H_ 22 #define FST_DFS_VISIT_H_ 81 using Arc =
typename FST::Arc;
87 return pool->Allocate();
93 dfs_state->~DfsState<
FST>();
94 pool->Free(dfs_state);
111 template <
class FST,
class Visitor,
class ArcFilter>
113 bool access_only =
false) {
114 using Arc =
typename FST::Arc;
115 using StateId =
typename Arc::StateId;
116 visitor->InitVisit(fst);
117 const auto start = fst.Start();
119 visitor->FinishVisit();
123 enum class StateColor : uint8_t {
128 std::vector<StateColor> state_color;
129 std::stack<internal::DfsState<FST> *> state_stack;
132 StateId nstates = fst.NumStatesIfKnown().value_or(start + 1);
133 const bool expanded = fst.Properties(
kExpanded,
false);
134 state_color.resize(nstates, StateColor::kWhite);
139 for (
auto root = start; dfs && root < nstates;) {
140 state_color[root] = StateColor::kGrey;
142 dfs = visitor->InitState(root, root);
143 while (!state_stack.empty()) {
144 auto *dfs_state = state_stack.top();
145 const auto s = dfs_state->state_id;
146 if (s >=
static_cast<decltype(s)
>(state_color.size())) {
148 state_color.resize(nstates, StateColor::kWhite);
151 if (!dfs || aiter.
Done()) {
152 state_color[s] = StateColor::kBlack;
155 if (!state_stack.empty()) {
156 auto *parent_state = state_stack.top();
157 auto &piter = parent_state->arc_iter;
158 visitor->FinishState(s, parent_state->state_id, &piter.Value());
165 const auto &arc = aiter.
Value();
167 static_cast<decltype(arc.nextstate)>(state_color.size())) {
168 nstates = arc.nextstate + 1;
169 state_color.resize(nstates, StateColor::kWhite);
175 const auto next_color = state_color[arc.nextstate];
176 switch (next_color) {
177 case StateColor::kWhite:
178 dfs = visitor->TreeArc(s, arc);
180 state_color[arc.nextstate] = StateColor::kGrey;
181 state_stack.push(
new (&state_pool)
183 dfs = visitor->InitState(arc.nextstate, root);
185 case StateColor::kGrey:
186 dfs = visitor->BackArc(s, arc);
189 case StateColor::kBlack:
190 dfs = visitor->ForwardOrCrossArc(s, arc);
195 if (access_only)
break;
197 for (root = root == start ? 0 : root + 1;
198 root < nstates && state_color[root] != StateColor::kWhite; ++root) {
201 if (!expanded && root == nstates) {
202 for (; !siter.
Done(); siter.
Next()) {
203 if (siter.
Value() == nstates) {
205 state_color.push_back(StateColor::kWhite);
211 visitor->FinishVisit();
214 template <
class Arc,
class Visitor>
221 #endif // FST_DFS_VISIT_H_
static void Destroy(DfsState< FST > *dfs_state, MemoryPool< DfsState< FST >> *pool)
void DfsVisit(const FST &fst, Visitor *visitor, ArcFilter filter, bool access_only=false)
const Arc & Value() const
DfsState(const FST &fst, StateId s)
typename Arc::StateId StateId
ArcIterator< FST > arc_iter
constexpr uint64_t kExpanded