[elixir! #0084] 關於 DFA(確定性有限自動機)的那些事兒

Ljzn發表於2022-02-10

最近在看 編譯原理 這本書,感覺是很棒的入門書(指難度由淺入深深深深)。前兩章主要是一些概念性的東西,第三章就開始動真格的,上程式碼上公式了。不自己實現一下,根本就是看得雲裡霧裡的。所以接下來一段時間可能會不定期地更新一些關於我在 編譯原理 這本書裡看到的東西的實現的文章。

書本的第三章介紹了 DFA 是如何對字串進行匹配的,例如,正規表示式 (a|b)*abb 可以轉換為以下的 DFA 程式碼。通過狀態機的機制在讀取字元時切換當前狀態,並根據最後的狀態來確定匹配是否成功。

defmodule DFA do
  
  def init(string) do
    %{
      s: 0,
      chars: String.to_charlist(string)
    }
  end

  def run(%{s: s, chars: [h | t]}) do
    s = move(s, h)
    run(%{s: s, chars: t})
  end
  def run(%{s: s, chars: []}) do
    if s in f() do
      :yes
    else
      :no
    end
  end

  defp move(0, ?a), do: 1
  defp move(0, ?b), do: 0
  defp move(1, ?a), do: 1
  defp move(1, ?b), do: 2
  defp move(2, ?a), do: 1
  defp move(2, ?b), do: 3
  defp move(3, ?a), do: 1
  defp move(3, ?b), do: 0

  defp f(), do: [3]

end

這個 DFA 只會匹配到以 "abb" 結尾的字串:

DFA.init("ababb")
|> DFA.run()

# :yes

DFA.init("ababa")
|> DFA.run()

# :no

是不是很神奇呢

相關文章