使用Vim脚本查找两个字符串中最大的公共部分

时间:2014-02-07 20:10:45

标签: regex vim regex-greedy

我有两个字符串变量。第二个字符串是第一个字符串的更改版本。像这样:

let a = 'this is a string'
let b = 'oh this is another string'

我想找到两者中最大的子字符串。

在示例中,结果为this is a

在Vim中最简单的方法是什么,考虑到变量可能包含任意一行文本?

我最初的想法是连接两个字符串

this is a string|oh this is another string

然后将matchlist()与此正则表达式一起使用:

\v(.+).*\|.*\1

不幸的是,括号中的组刚匹配' string'

1 个答案:

答案 0 :(得分:1)

试试这个:

function! LongestCommonSubstring(foo, bar)
  let longest = ''
  for n in range(strlen(a:foo))
    let common = matchlist(strpart(a:foo, n) . '|' . a:bar, '\v(.+).*\|.*\1')[1]
    if strlen(common) > strlen(longest)
      let longest = common
    endif
  endfor
  return longest
endfun

对于长字符串,它可能比@ Jeff链接中的算法效率低,但它可以处理this is a stringoh this is another string

最长的行正好是80个字符,所以按照通常的标准,它可以,但它足够密集,可能更清楚地将它拆分:

    let pasted = strpart(a:foo, n) . '|' . a:bar
    let common = matchlist(pasted, '\v(.+).*\|.*\1')[1]

或者

    let common = matchstr(pasted, '\v\zs(.+)\ze.*\|.*\1')

当然,这仅在|不在任何一个字符串中时才有效。