ウォンツテック

そでやまのーと

前回のコーディングでntransというNFA用のデータ構築まで出来、次はnnodeという状態番号を元にしたデータを作成し、その後DFAを構築する。

まず、NFAのntransからnnodeへの変換を考える。
struct Nnode {
  char ch;
  int to;
  Nnode* next;
} *nnode[MAX];
nnodeの添え字はNFAの状態番号とし(ntransのfrom)以下のアルゴリズムで変換する
while(ntransを全てチェック) {
  if (nnode[from]が既に存在する)
    Nnodeを新しく作成し、nnode[from]のnext(リンクリスト)の先頭に追加する。
  else
    nnode[from]を新しく作成する。
}

NFAからDFAへの変換は部分集合構成法とする。
すなわち、ある状態番号xからある文字chで遷移する状態番号の集合をS''とし、さらにその状態からEMPTYで遷移可能な状態番号を加えた集合をS'とする。これを状態番号xが属している集合について全て行い、それらの和集合をSとした時、そのSをDFA上の状態要素とする。
また、NFAの初期状態はそれ自身をただ一つの要素として持つ集合とする。

struct Dtrans {
  int to;  // nnodeの状態番号
  Dtrans* nextTo;  //この添え字のDFAが遷移可能なNFAの状態番号をListで連結しておく
} *dtrans[DFA_MAX]; //添え字はdnodeの添え字と同じでDFAの状態番号
struct Dnode {
  char c;
  Dnode* to; //dnodeのto
} *dnode[DFA_MAX];

状態0のdtransとdnodeを作成する。
while (新しい遷移が得られなくなるまで繰り返す) {
//dnode要検査数>=カレントdnodeチェック番号の間は繰り返す
  while (現在のdnodeから遷移可能なnnodeを全てチェック)
    while (nnodeの連結リストを全てチェック) {
      if (ntrans->ch != EMPTY)
        このdnodeで新しい文字が出た場合、新規状態のdnodeを作成する。 また、その場合は現在のdnodeから連結リストとしてtoの先頭に追加し、dnodeの要検査数をインクリメントする。
    遷移先をdtransに記録する
     else if (ntrans-> ch == EMPTY)
        遷移先をdtransに記録する
    }
    現在のdnodeの遷移チェック完了
  カレントのdnodeチェック番号をインクリメントする
  }
}

今一しっくり来てないから実装時に大幅に変えるかも。