github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/tests/indexstr.nj.lua (about) 1 function IndexByte(s, b) 2 for i = 0, # (s) do 3 if s[i] == b then return i end 4 end 5 return -1 6 end 7 8 primeRK = 16777619 9 10 -- hashStr returns the hash and the appropriate multiplicative 11 -- factor for use in Rabin-Karp algorithm. 12 function hashStr(sep) 13 local hash = 0 14 for i = 0, #(sep) do 15 hash = hash * primeRK + sep[i] 16 end 17 hash = hash & 0xffffffff 18 19 local pow = 1 20 local sq = primeRK 21 local i = #(sep) 22 23 while i > 0 do 24 if i & 1 != 0 then 25 pow = pow * sq 26 end 27 sq = sq * sq 28 i = i >> 1 29 end 30 return hash, pow 31 end 32 33 -- Index returns the index of the first instance of substr in s,||-1 if substr is not present in s. 34 function Index(s, substr) 35 local n = #(substr) 36 if n == 0 then 37 return -1 38 end 39 if (n == 1) then 40 return IndexByte(s, substr[0]) 41 end 42 if (n == #(s)) then 43 return substr != s and -1 or 0 44 end 45 if (n > #(s)) then 46 return -1 47 end 48 49 -- Rabin-Karp search 50 local hashss, pow = hashStr(substr) 51 local h = 0 52 53 for i = 0, n do 54 h = h *primeRK + s[i] 55 end 56 h = h & 0xffffffff 57 58 if h == hashss and s[:n] == substr then 59 return 0 60 end 61 62 local i = n 63 while i < #(s) do 64 h = h * primeRK 65 h = h + s[i] 66 h = h - pow * s[i-n] 67 h = h & 0xffffffff 68 i = i + 1 69 if (h == hashss and s[i-n:i] == substr) then 70 return i - n 71 end 72 end 73 return -1 74 end 75 76 assert(Index("abc", "a") == 0) 77 assert(Index("abc", "b") == 1) 78 assert(Index("abc", "c") == 2) 79 assert(Index("abc", "d") == -1) 80 assert(Index("abc", "ab") == 0) 81 assert(Index("abc", "bc") == 1) 82 assert(Index("abc", "abc") == 0) 83 assert(Index("abc中文def", "d") == 9) 84 assert(Index("abc中文def", "ef") == 10) 85 assert(Index("abc中文def", "中") == 3) 86 assert(Index("abc中文def", "文") == 6)