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)