size_t minimize(const DFA& dfa, const vector<size_t>& terminalStates) { for (int stateA_ = dfa.statesCount() - 1; stateA_ >= 0; --stateA_) { size_t stateA = stateA_; if (!dfa.isReachable(stateA)) { continue; } for (int stateB_ = 0; stateB_ <= stateA_; ++stateB_) { size_t stateB = stateB_; if (!dfa.isReachable(stateB)) { continue; } if (stateA < stateB) { std::swap(stateA, stateB); } for (size_t index = 0; index < dfa.alphaberSize(); ++index) { char symbol = 'a' + index; size_t newStateA = dfa.adjcencyState(symbol, stateA); size_t newStateB = dfa.adjcencyState(symbol, stateB); if (newStateA < newStateB) { std::swap(newStateA, newStateB); } pairGraph[newStateA][newStateB].push_back(make_pair(stateA, stateB)); } } } return countNonEquivalentStates(dfa, terminalStates); }
size_t countNonEquivalentStates(const DFA& dfa, const vector<size_t>& terminalStates) { queue<pair<size_t, size_t> > bfsQueue; for (size_t index = 0; index < terminalStates.size(); ++index) { int terminalState = terminalStates[index]; if (!dfa.isReachable(terminalState)) { continue; } for (int state = 0; state < dfa.statesCount(); ++state) { if (!dfa.isReachable(state) || dfa.isTerminal(state)) { continue; } if (terminalState < state) { bfsQueue.push(make_pair(state, terminalState)); used[state][terminalState] = true; } else { bfsQueue.push(make_pair(terminalState, state)); used[terminalState][state] = true; } } } while (!bfsQueue.empty()) { pair<size_t, size_t> begin = bfsQueue.front(); bfsQueue.pop(); size_t stateA = begin.first; size_t stateB = begin.second; for (size_t index = 0; index < pairGraph[stateA][stateB].size(); ++index) { size_t newStateA = pairGraph[stateA][stateB][index].first; size_t newStateB = pairGraph[stateA][stateB][index].second; if (!used[newStateA][newStateB]) { bfsQueue.push(make_pair(newStateA, newStateB)); used[newStateA][newStateB] = true; } } } Sets sets(dfa.statesCount()); for (int stateA = dfa.statesCount() - 1; stateA >= 0; --stateA) { for (int stateB = 0; stateB < stateA; ++stateB) { if (!used[stateA][stateB] && dfa.isReachable(stateA) && dfa.isReachable(stateB)) { sets.merge(stateA, stateB); } } } return sets.count(); }