2014-02-07 49 views
0

我有兩個字符串變量。第二個字符串是第一個字符串的更改版本。像這樣:使用Vim腳本查找兩個字符串的最大公共部分

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

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

在該示例中,結果爲this is a

考慮到變量可能包含任意文本行,在Vim中這樣做的最簡單方法是什麼?

我最初的想法是Concat的兩個字符串

this is a string|oh this is another string

然後用matchlist()用這個表達式:

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

不幸的是,在括號中的組只匹配' string'

+0

您可以嘗試將[這些](http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring)實現之一翻譯成vimscript。 – Jeff

+0

有趣的,我試過':echo matchlist('這是一個字符串|哦這是另一個字符串','\ v(。+)。* \ |。* \ 1')'列表的第二項是' '這是'',而不是''串'「。但是,這是因爲「這是一個首先,而不是因爲它最長。我不確定這是可能的正則表達式。 @傑夫的建議可能是最好的選擇。 – benjifisher

回答

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 

對於長字符串,它可能比@傑夫的鏈接算法效率較低,但它處理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') 

當然,這隻適用於|不在任一字符串中。

相關問題