-
Notifications
You must be signed in to change notification settings - Fork 0
/
trie.lua
104 lines (95 loc) · 2.51 KB
/
trie.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
local mt; mt = {
__metatable = "Trie",
__index = {
add = function (t, ...)
local str, k = ...
if type(str) ~= "string" then return false end
if select("#", ...) == 1 then k = true end
if k == nil then return false end
for ch in str:gmatch "." do
if rawequal(rawget(t, ch), nil) then rawset(t, ch, {}) end
t = rawget(t, ch)
end
rawset(t, true, k)
return true
end,
remove = function (t, str)
local cache_k = {}
local cache_t = setmetatable({[0] = t}, {__mode = "v"})
for x = 1, #str do
local ch = str:sub(x, x)
t = rawget(t, ch)
if t == nil then return false end
cache_k[#cache_k + 1] = ch
cache_t[#cache_t + 1] = t
end
local z = rawget(t, true)
if z == nil then return false end
rawset(t, true, nil)
for i = #cache_t, 1, -1 do
if next(cache_t[i]) ~= nil then break end
rawset(cache_t[i - 1], cache_k[i], nil)
end
return true
end,
clear = function (t)
local function f (t)
for k, v in next, t do
if k ~= true then f(v) end
rawset(t, k, nil)
end
end
f(t)
end,
get = function (t, str)
for x = 1, #str do
t = rawget(t, str:sub(x, x))
if t == nil then return nil end
end
return rawget(t, true)
end,
lookup = function (t, str, beg)
beg = beg or 1
local x = beg - 1
local longest, val
repeat
if rawget(t, true) ~= nil then
longest, val = str:sub(beg, x), rawget(t, true)
end
x = x + 1
t = rawget(t, str:sub(x, x))
until t == nil;
return longest, val
end,
begins = function (t, str)
local out = {}
for x = 1, #str do
t = rawget(t, str:sub(x, x))
if t == nil then return out end
end
local function f (t, prefix)
for k, v in next, t do
if k == true then out[#out + 1] = prefix
else f(v, prefix .. k) end
end
end
f(t, str)
return out
end,
clone = function (t)
local z = setmetatable({}, mt)
for k, v in pairs(t) do z:add(k, v) end
return z
end,
},
__pairs = function (t)
local function f (t, prefix)
for k, v in next, t do
if k == true then coroutine.yield(prefix, v)
else f(v, prefix .. k) end
end
end
return coroutine.wrap(f), t, ""
end,
}
return function () return setmetatable({}, mt) end