\startluacode

  local math, table, utf = math, table, utf
  local max = math.max
  local insert = table.insert
  local len, sub = utf.len, utf.sub
  local interfaces = interfaces
  local constants = interfaces.constants
  local c_command = constants.command

  local implement = interfaces.implement

  local function LCS(s1, s2)
    local m, n = len(s1), len(s2)
    local c = {}
    for i = 0, m do
      c[i] = {}
      for j = 0, n do
        c[i][j] = 0
      end
    end
    for i = 1, m do
      for j = 1, n do
        if sub(s1, i, i) == sub(s2, j, j) then
          c[i][j] = c[i - 1][j - 1] + 1
        else
          c[i][j] = max(c[i - 1][j], c[i][j - 1])
        end
      end
    end
    return c
  end

  local function backtrack(c, s1, s2, i, j)
    if i == 0 or j == 0 then
      return ""
    elseif sub(s1, i, i) == sub(s2, j, j) then
      return backtrack(c, s1, s2, i - 1, j - 1) .. sub(s1, i, i)
    elseif c[i][j - 1] > c[i - 1][j] then
      return backtrack(c, s1, s2, i, j - 1)
    else
      return backtrack(c, s1, s2, i - 1, j)
    end
  end

  local function difftable(s1, s2)
    local c = LCS(s1, s2)
    local lcs = backtrack(c, s1, s2, len(s1), len(s2))

    local result = {}
    local i, j = 1, 1

    local i_, j_
    local aux

    for k = 1, #lcs do
      i_, j_ = i, j
      while sub(s1, i, i) ~= sub(lcs, k, k) do
        i = i + 1
      end
      aux = sub(s1, i_, i-1)

      if #aux > 0 then
        insert(result, {opt = false, data = aux})
      end

      while sub(s2, j, j) ~= sub(lcs, k, k) do
        j = j + 1
      end
      aux = sub(s2, j_, j-1)

      if #aux > 0 then
        insert(result, {opt = true, data = aux})
      end

      insert(result, sub(lcs, k, k))
      i = i + 1
      j = j + 1
    end

    aux = sub(s1, i, len(s1))
    if #aux > 0 then
      insert(result, {opt = false, data = aux})
    end

    aux = sub(s2, j, len(s2))
    if #aux > 0 then
      insert(result, {opt = false, data = aux})
    end

    return result
  end

  implement{
    name = "correction",
    arguments = "2 strings",
    actions = function(s1, s2)
      local diff = difftable(s1, s2) 
      for _, v in ipairs(diff) do
        if type(v) == "string" then
          context(v)
        elseif type(v) == "table" then
          context.correctionparameter(c_command .. (v.opt and "a" or "b"), v.data)
        end
      end
    end
  }
\stopluacode

\unprotect

\installnamespace                          {correction}
\installsimplecommandhandler\????correction{correction}\????correction

\setupcorrection
  [\c!command a=\underbar,
   \c!command b=\overstrike]

\tolerant\protected\def\correction[#1]#:#2#3%
  {\begingroup\setupcorrection[#1]\clf_correction{#2}{#3}\endgroup}

\protect

\starttext

\correction{alverja}{arveja}

\correction{irregardless}{regardless}

\correction{transgiversar}{tergiversar}

\stoptext