1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// dfs-visit.h 2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License"); 4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License. 5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at 6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// http://www.apache.org/licenses/LICENSE-2.0 8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software 10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS, 11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and 13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License. 14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc. 16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley) 17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file 19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Depth-first search visitation. See visit.h for more general 20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// search queue disciplines. 21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_DFS_VISIT_H__ 23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_DFS_VISIT_H__ 24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <stack> 26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <vector> 27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::vector; 28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/arcfilter.h> 30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/fst.h> 31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst { 34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Visitor Interface - class determines actions taken during a Dfs. 36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If any of the boolean member functions return false, the DFS is 37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// aborted by first calling FinishState() on all currently grey states 38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// and then calling FinishVisit(). 39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Note this is similar to the more general visitor interface in visit.h 41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// except that FinishState returns additional information appropriate only for 42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// a DFS and some methods names here are better suited to a DFS. 43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// template <class Arc> 45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// class Visitor { 46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// public: 47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// typedef typename Arc::StateId StateId; 48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Visitor(T *return_data); 50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked before DFS visit 51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// void InitVisit(const Fst<Arc> &fst); 52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked when state discovered (2nd arg is DFS tree root) 53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// bool InitState(StateId s, StateId root); 54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked when tree arc examined (to white/undiscovered state) 55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// bool TreeArc(StateId s, const Arc &a); 56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked when back arc examined (to grey/unfinished state) 57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// bool BackArc(StateId s, const Arc &a); 58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked when forward or cross arc examined (to black/finished state) 59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// bool ForwardOrCrossArc(StateId s, const Arc &a); 60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked when state finished (PARENT is kNoStateID and ARC == NULL 61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // when S is tree root) 62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// void FinishState(StateId s, StateId parent, const Arc *parent_arc); 63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// // Invoked after DFS visit 64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// void FinishVisit(); 65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// }; 66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// An Fst state's DFS status 68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsWhite = 0; // Undiscovered 69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsGrey = 1; // Discovered & unfinished 70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsBlack = 2; // Finished 71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// An Fst state's DFS stack state 73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc> 74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct DfsState { 75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DfsState(const Fst<Arc> &fst, StateId s): state_id(s), arc_iter(fst, s) {} 78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId state_id; // Fst state ... 80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ArcIterator< Fst<Arc> > arc_iter; // and its corresponding arcs 81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Performs depth-first visitation. Visitor class argument determines 85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// actions and contains any return data. ArcFilter determines arcs 86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// that are considered. 87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Note this is similar to Visit() in visit.h called with a LIFO 89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// queue except this version has a Visitor class specialized and 90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// augmented for a DFS. 91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc, class V, class ArcFilter> 92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid DfsVisit(const Fst<Arc> &fst, V *visitor, ArcFilter filter) { 93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson visitor->InitVisit(fst); 96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId start = fst.Start(); 98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (start == kNoStateId) { 99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson visitor->FinishVisit(); 100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return; 101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<char> state_color; // Fst state DFS status 104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson stack<DfsState<Arc> *> state_stack; // DFS execution stack 105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId nstates = start + 1; // # of known states in general case 107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool expanded = false; 108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (fst.Properties(kExpanded, false)) { // tests if expanded case, then 109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nstates = CountStates(fst); // uses ExpandedFst::NumStates(). 110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson expanded = true; 111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color.resize(nstates, kDfsWhite); 114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateIterator< Fst<Arc> > siter(fst); 115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Continue DFS while true 117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool dfs = true; 118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Iterate over trees in DFS forest. 120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (StateId root = start; dfs && root < nstates;) { 121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color[root] = kDfsGrey; 122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_stack.push(new DfsState<Arc>(fst, root)); 123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson dfs = visitor->InitState(root, root); 124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson while (!state_stack.empty()) { 125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DfsState<Arc> *dfs_state = state_stack.top(); 126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId s = dfs_state->state_id; 127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s >= state_color.size()) { 128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nstates = s + 1; 129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color.resize(nstates, kDfsWhite); 130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ArcIterator< Fst<Arc> > &aiter = dfs_state->arc_iter; 132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!dfs || aiter.Done()) { 133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color[s] = kDfsBlack; 134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson delete dfs_state; 135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_stack.pop(); 136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!state_stack.empty()) { 137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DfsState<Arc> *parent_state = state_stack.top(); 138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId p = parent_state->state_id; 139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ArcIterator< Fst<Arc> > &piter = parent_state->arc_iter; 140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson visitor->FinishState(s, p, &piter.Value()); 141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson piter.Next(); 142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson visitor->FinishState(s, kNoStateId, 0); 144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson continue; 146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const Arc &arc = aiter.Value(); 148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.nextstate >= state_color.size()) { 149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nstates = arc.nextstate + 1; 150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color.resize(nstates, kDfsWhite); 151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!filter(arc)) { 153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson aiter.Next(); 154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson continue; 155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson int next_color = state_color[arc.nextstate]; 157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson switch (next_color) { 158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson default: 159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson case kDfsWhite: 160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson dfs = visitor->TreeArc(s, arc); 161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!dfs) break; 162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color[arc.nextstate] = kDfsGrey; 163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_stack.push(new DfsState<Arc>(fst, arc.nextstate)); 164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson dfs = visitor->InitState(arc.nextstate, root); 165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson break; 166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson case kDfsGrey: 167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson dfs = visitor->BackArc(s, arc); 168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson aiter.Next(); 169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson break; 170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson case kDfsBlack: 171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson dfs = visitor->ForwardOrCrossArc(s, arc); 172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson aiter.Next(); 173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson break; 174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Find next tree root 178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (root = root == start ? 0 : root + 1; 179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson root < nstates && state_color[root] != kDfsWhite; 180dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin ++root) { 181dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin } 182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Check for a state beyond the largest known state 184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!expanded && root == nstates) { 185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (; !siter.Done(); siter.Next()) { 186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (siter.Value() == nstates) { 187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++nstates; 188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_color.push_back(kDfsWhite); 189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson break; 190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson visitor->FinishVisit(); 195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} 196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc, class V> 199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid DfsVisit(const Fst<Arc> &fst, V *visitor) { 200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DfsVisit(fst, visitor, AnyArcFilter<Arc>()); 201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} 202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} // namespace fst 204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif // FST_LIB_DFS_VISIT_H__ 206