各文字列に異なる整数値IDを割り当てる string ID a 1 a b 2 b a 3 c a a 4 c b 5 ❏ 文字列集合{S1, … , Sn}は辞書順 に並んでいるとし, i番目の文字列SiのIDはiとする. ❏ string-to-ID (文字列→IDを応答) ID-to-string (ID→文字列を応答) の2つの機能を提供する
❏ DFAのパスに整数値の重みを 割り当てることで,string-to-IDとID-to-stringを実現 string ID a 1 a b 2 b a 3 c a a 4 c b 5 a | 2 b | 1 b | 1 c | 2 a | 1 b | 1 | 5 重み:遷移先以降の経路パターンの数 a | 1
string ID a 1 a b 2 b a 3 c a a 4 c b 5 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 重み:遷移先以降の経路パターンの数 ❏ DFAのパスに整数値の重みを 割り当てることで,string-to-IDとID-to-stringを実現
string ID a 1 a b 2 b a 3 c a a 4 c b 5 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 重み:遷移先以降の経路パターンの数 ❏ DFAのパスに整数値の重みを 割り当てることで,string-to-IDとID-to-stringを実現
string ID a 1 a b 2 b a 3 c a a 4 c b 5 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 重み:遷移先以降の経路パターンの数 ❏ DFAのパスに整数値の重みを 割り当てることで,string-to-IDとID-to-stringを実現
入力文字列: Sin 出力ID: IDout w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout {
入力文字列: Sin = ‘caa’ 出力ID: IDout = 4 w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout { C = 0
入力文字列: Sin = ‘caa’ 出力ID: IDout = 4 w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout { C = 0 + 2 = 2
入力文字列: Sin = ‘caa’ 出力ID: IDout = 4 w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout { C = 2 + 1 = 3
入力文字列: Sin = ‘caa’ 出力ID: IDout = 4 w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout { C = 3
入力文字列: Sin = ‘caa’ 出力ID: IDout = 4 w(p): パスpの重み カウンター変数: C = 0 a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ for p ∈ 現在の状態のパスから辞書順: if pが経路ではない C = C + w(p) else 遷移を実行し,次の状態へ Sinによる遷移が終了したとき,C = IDout { C = 3 + 1 = 4 IDout = C = 4
入力ID: IDin 出力文字列: Sout w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 {
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 4
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 4 - 2 = 2
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 2 - 1 = 1
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 1
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 1
入力ID: IDin = 4 出力文字列: Sout = ‘caa’ w(p): パスpの重み カウンター変数: C = IDin a | 2 b | 1 b | 1 a | 1 c | 2 a | 1 b | 1 | 5 ❏ for p ∈ 現在の状態のパスから辞書順: if w(p) < C C = C - w(p) if w(p) > C pによる遷移を実行 if w(p) = C pによる遷移を実行 if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { C = 1 - 1 = 0 Sout = ‘caa’
Sin 出力ID: IDout r(p): パスpの順位数 カウンター変数: C = 0 a | 0 b | 0 b | 2 a | 0 c | 3 a | 0 b | 0 | 0 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ C = C + r(p) Sinによる遷移が終了したとき,C = IDout {
Sin = ‘caa’ 出力ID: IDout = 4 r(p): パスpの順位数 カウンター変数: C = 0 a | 0 b | 0 b | 2 a | 0 c | 3 a | 0 b | 0 | 0 Sinによる経路上の各状態で以下を実行 ❏ if 受理状態 C = C + 1 ❏ C = C + r(p) Sinによる遷移が終了したとき,C = IDout { IDout = 0 + 3 + 0 + 0 + 1 = 4
IDin 出力文字列: Sout r(p): パスpの順位数 カウンター変数: C = 0 重み変数: W = 5 a | 0 b | 0 b | 2 a | 0 c | 3 a | 0 b | 0 5 | 0 ❏ for p ∈ 現在の状態のパスから辞書順: if pが最後のパスではない: w = r(pの次のパス) - r(p) else: w = W - r(p) if w < C C = C - w if w > C pによる遷移を実行,W = w if w = C pによる遷移を実行,W = w if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { ルートの重みだけ必要
IDin 出力文字列: Sout r(p): パスpの順位数 カウンター変数: C = 0 重み変数: W = 5 a | 0 b | 0 b | 2 a | 0 c | 3 a | 0 b | 0 5 | 0 ❏ for p ∈ 現在の状態のパスから辞書順: if pが最後のパスではない: w = r(pの次のパス) - r(p) else: w = W - r(p) if w < C C = C - w if w > C pによる遷移を実行,W = w if w = C pによる遷移を実行,W = w if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { ルートの重みだけ必要 ① 5 ② 元々の重み =順位数の差分 ② 次のパスの順位数との 差分から重みを取り出す 後の操作は同じ
IDin 出力文字列: Sout r(p): パスpの順位数 カウンター変数: C = 0 重み変数: W = 5 a | 0 b | 0 b | 2 a | 0 c | 3 a | 0 b | 0 5 | 0 ❏ for p ∈ 現在の状態のパスから辞書順: if pが最後のパスではない: w = r(pの次のパス) - r(p) else: w = W - r(p) if w < C C = C - w if w > C pによる遷移を実行,W = w if w = C pによる遷移を実行,W = w if 受理状態 C = C - 1 if C = 0 return 経路上の文字列 { ルートの重みだけ必要 5 競技単調増加列の中から C以下の最大のパスを探す 問題と考えられる.