Пример #1
0
void
ComputeLongestPathLength1( const DFA& dfa
						 , typename DFA::state_id_t RootState
						 , valvec<LenType>& lens
						 )
{
	typedef typename DFA::state_id_t state_id_t;
	typedef typename DFA::transition_t transition_t;
	valvec<unsigned char> color(dfa.total_states(), 0);
	valvec<state_id_t> stack;
	valvec<state_id_t> index(dfa.total_states()+1, 0);
	valvec<state_id_t> backlink;
	state_id_t InverseRoot = DFA::null_state;

	// for reduce memory usage, use indexed adjacent difference structure
	// first pass traverse dfa from RootState:
	//   caculate the number of incoming transitions of each state
	//   index[state_id] = number of incoming transitions of state_id
	stack.push_back(RootState);
	color[RootState] = 1;
	while (!stack.empty()) {
		state_id_t parent = stack.back(); stack.pop_back();
		dfa.for_each_dest(parent,
			[&](state_id_t, const transition_t& t) {
				state_id_t child = t;
				if (color[child] < 1) {
					color[child] = 1;
					stack.push_back(child);
				}
				index[child+1]++;
			});
		if (!dfa.has_children(parent)) {
			assert(DFA::null_state == InverseRoot);
			if (DFA::null_state != InverseRoot) {
				throw std::logic_error("ComputeLongestPathLength: more than one InverseRoot");
			}
			InverseRoot = parent;
		}
	}
	assert(DFA::null_state != InverseRoot);
	if (DFA::null_state == InverseRoot) {
		throw std::logic_error("ComputeLongestPathLength: not found InverseRoot");
	}
	if (!dfa.is_term(InverseRoot)) {
		throw std::logic_error("ComputeLongestPathLength: InverseRoot is not final state");
	}
	if (0 != index[RootState]) {
		throw std::logic_error("ComputeLongestPathLength: found back link to RootState");
	}
	for (size_t i = 2; i < index.size(); ++i) index[i] += index[i-1];

	// second pass traverse dfa from RootState:
	//   backlink[index[s] ... index[s+1]) is the backlinks of state s
	stack.push_back(RootState);
	color[RootState] = 2;
	backlink.resize_no_init(index.back());
	{
		valvec<state_id_t> index2 = index;
		while (!stack.empty()) {
			state_id_t parent = stack.back(); stack.pop_back();
			dfa.for_each_dest(parent,
				[&](state_id_t, const transition_t& t) {
					state_id_t child = t;
					if (color[child] < 2) {
						color[child] = 2;
						stack.push_back(child);
					}
					backlink[index2[child]++] = parent;
				});
		}
	}

	// traverse the inversed graph structure of dfa
	//   compute longest_path_length of state s from RootState
	lens.resize(dfa.total_states(), 0);
	stack.push_back(InverseRoot);
	color[InverseRoot] = 3;
	while (!stack.empty()) {
		state_id_t parent = stack.back();
		switch (color[parent]) {
		default:
			assert(0);
			throw std::runtime_error("ComputeLongestPathLength: unexpected 1");
		case 3: {
			size_t beg = index[parent+0];
			size_t end = index[parent+1];
			color[parent] = 4;
			for (size_t i = beg; i < end; ++i) {
				state_id_t child = backlink[i];
				switch (color[child]) {
				default:
					assert(0);
					throw std::runtime_error("ComputeLongestPathLength: unexpected 2");
					break;
				case 2: // not touched
					stack.push_back(child);
					color[child] = 3;
					break;
				case 3: // forward edge
					break;
				case 4: // back edge
					if (child == parent)
						throw std::logic_error("ComputeLongestPathLength: found a self-loop");
					else
						throw std::logic_error("ComputeLongestPathLength: found a non-self-loop");
				case 5: // cross edge
					break;
				}
			}
			break; }
		case 4: {
			size_t beg = index[parent+0];
			size_t end = index[parent+1];
			for (size_t i = beg; i < end; ++i) {
				state_id_t child = backlink[i];
				assert(5 == color[child]);
				lens[parent] = std::max(lens[parent], lens[child] + 1);
			}
			color[parent] = 5;
			stack.pop_back();
			break; }
		case 5:
			break;
		}
	}
}
Пример #2
0
void
ComputeLongestPathLength2( const DFA& dfa
						 , typename DFA::state_id_t RootState
						 , valvec<LenType>& lens
						 )
{
	typedef typename DFA::state_id_t   state_id_t;
	typedef typename DFA::transition_t trans_t;
	valvec<unsigned char> color(dfa.total_states(), 2);
	valvec<state_id_t> stack, topological;
	lens.resize(dfa.total_states(), 0);
	stack.push_back(RootState);
	color[RootState] = 3;
	while (!stack.empty()) {
		state_id_t parent = stack.back();
		switch (color[parent]) {
		default:
			assert(0);
			throw std::runtime_error("ComputeLongestPathLength: unexpected 1");
		case 3:
			color[parent] = 4;
			dfa.for_each_dest(parent, [&](state_id_t p, const trans_t& t) {
				state_id_t child = t;
				switch (color[child]) {
				default:
					assert(0);
					throw std::runtime_error("ComputeLongestPathLength: unexpected 2");
					break;
				case 2: // not touched
					stack.push_back(child);
					color[child] = 3;
					break;
				case 3: // forward edge
					break;
				case 4: // back edge
					if (child == p)
						throw std::logic_error("ComputeLongestPathLength: found a self-loop");
					else
						throw std::logic_error("ComputeLongestPathLength: found a non-self-loop");
				case 5: // cross edge
					break;
				}
			});
			break;
		case 4:
			topological.push_back(parent);
			color[parent] = 5;
			stack.pop_back();
			break;
		case 5:
			break;
		}
	}
	for (size_t i = topological.size(); i > 0; --i) {
		state_id_t parent = topological[i-1];
		dfa.for_each_dest(parent, [&](state_id_t p, const trans_t& t) {
			state_id_t child = t;
			assert(5 == color[child]);
			lens[child] = std::max(lens[p] + 1, lens[child]);
		});
	}
}