Advertisement
SirNickolas

Suffix Automata Visualizer

Aug 27th, 2016
381
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Nim 3.04 KB | None | 0 0
  1. {.this: self.}
  2.  
  3. import strfmt
  4. import tables
  5.  
  6.  
  7. # Suffix Automaton implementation.
  8. type
  9.     NodePtr = ptr Node
  10.  
  11.     Node = object
  12.         length: int
  13.         firstPos: int
  14.         isClone: bool
  15.         done: bool
  16.         next: Table[char, NodePtr]
  17.         link: NodePtr
  18.  
  19.  
  20. proc init(self: var Node) =
  21.     length = 0
  22.     firstPos = -1
  23.     isClone = false
  24.     done = false
  25.     next = initTable[char, NodePtr]()
  26.     link = nil
  27.  
  28.  
  29. proc init(self: var Node; length: int) =
  30.     self.length = length
  31.     isClone = false
  32.     done = false
  33.     next = initTable[char, NodePtr]()
  34.  
  35.  
  36. proc init(self: var Node; node: Node) =
  37.     self = node
  38.  
  39.  
  40. let
  41.     s = stdin.readLine()
  42.     n = len s
  43.  
  44. var
  45.     lastNode = -1
  46.     nodes = newSeq[Node](n shl 1)
  47.  
  48.  
  49. proc newNode(arg: int | Node): NodePtr =
  50.     inc lastNode
  51.     init nodes[lastNode], arg
  52.     addr nodes[lastNode]
  53.  
  54.  
  55. proc add(root: var Node; c: char; last: NodePtr): NodePtr =
  56.     var node = last
  57.     result = newNode(node.length + 1)
  58.     result.firstPos = node.length
  59.     while node != nil and not node.next.hasKeyOrPut(c, result):
  60.         node = node.link
  61.     if node == nil:
  62.         result.link = addr root
  63.     else:
  64.         var q = node.next[c]
  65.         if q.length == node.length + 1:
  66.             result.link = q
  67.         else:
  68.             var clone = newNode q[]
  69.             clone.isClone = true
  70.             clone.length = node.length + 1
  71.             q.link = clone
  72.             result.link = clone
  73.             while true:
  74.                 node.next.withValue(c, value) do:
  75.                     if value[] != q:
  76.                         break
  77.                     value[] = clone
  78.                 do: # Not found.
  79.                     break
  80.                 node = node.link
  81.                 if node == nil:
  82.                     break
  83.  
  84.  
  85. # DOT file generation.
  86. proc writeformat(o: var Writer; node: NodePtr; fmt: Format) =
  87.     write o, 'n'
  88.     writeformat o, cast[uint](node), fmt
  89.  
  90.  
  91. proc escape(c: char): string =
  92.     case c
  93.     of '\t':
  94.         "\\\t"
  95.     of '"':
  96.        "\\\""
  97.     of '\\':
  98.         "\\\\"
  99.     else:
  100.         var s = "."
  101.         s[0] = c
  102.         s
  103.  
  104.  
  105. proc label(self: Node): string =
  106.     result = "\""
  107.     for i in firstPos - length + 1 .. firstPos:
  108.         result &= escape s[i]
  109.     result &= '"'
  110.  
  111.  
  112. proc printMeta(self: var Node) =
  113.    var attrs = @[["label", self.label]]
  114.    if isClone:
  115.        attrs.add(["shape", "Mcircle"])
  116.    printlnfmt "    {:X} [{:a| |=}]", addr self, attrs
  117.  
  118.  
  119. proc echo(self: var Node) =
  120.    if not done:
  121.        done = true
  122.        for c, node in next:
  123.            printlnfmt "    {:X} -> {:X} [label=\"{}\"]", addr self, node, escape c
  124.             echo node[]
  125.  
  126.  
  127. var root: Node
  128. init root
  129. var node = addr root
  130. for c in s:
  131.     node = root.add(c, node)
  132.  
  133. echo "digraph {\n    node [shape=circle]"
  134. printMeta root
  135. for i in 0..lastNode:
  136.     printMeta nodes[i]
  137. echo root
  138. echo "    edge [style=dotted dir=back arrowtail=empty]"
  139. for i in 0..lastNode:
  140.     printlnfmt "    {:X} -> {:X}", nodes[i].link, addr nodes[i]
  141. echo '}'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement