2014-02-07 3 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 ('это строка | oh это другая строка', '\ 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 string и oh 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') 

Конечно, это работает только в том случае, если | не находится ни в одной строке.

Смежные вопросы