0

Я пытаюсь найти самую длинную общую подстроку из двух строк с использованием рекурсии и DP. Обратите внимание, что я не имею в виду самую длинную непрерывную подпоследовательность. Таким образом, если две строки былиСамая длинная общая подстрока с использованием рекурсии и DP

String s1 = "abcdf"; String s2 = "bzcdf" 
Longest Common Substring == "cdf" (not "bcdf"). 
Basically they have to be continuous elements 

Я пытаюсь сделать это с помощью рекурсии и откаты. Однако проблема заключается в том, что если я использую рекурсию, например, ниже, то +1 добавляются заранее в фрейм, то есть выше в стеке вызовов, и не знают о том, являются ли персонажи действительно непрерывными элементами или нет , Итак, перейдя к примеру выше, «bcdf» будет ответом.

public class ThisIsLongestCommonSubsequence_NotSubstring { 
public static void main(String[] args) { 

    String s1 = "abcdgh"; 
    String s2 = "abefgh"; 
    System.out.println(fun(s1, s1.length()-1, s2, s2.length()-1)); 
} 

static int fun(String s1, int i, String s2, int j) 
{ 
    if(i == -1 || j == -1) 
     return 0; 

    int ret = 0; 
    if(s1.charAt(i) == s2.charAt(j)) 
     ret = fun(s1, i-1, s2, j-1) + 1; 
    else 
     ret = max(fun(s1, i-1, s2, j), fun(s1, i, s2, j-1)); 

    return ret; 
} 

static int max(int a, int b) 
{ 
    return a>b?a:b; 
} 
} 

На данный момент приведенный ниже код является тем, что я придумал. Обратите внимание, как я сброшу счет до 0, каждый раз, когда я нахожу несоответствие. И отслеживайте количество совпадающих символов, используя переменную с именем int count, и записывайте самое высокое значение в любой точке программы, используя переменную с именем int maxcount. Мой код ниже.

public class LongestContinuousSubstringGlobalvariable { 

static int maxcount = 0; 

public static void main(String[] args) { 
    String s1 = "abcdghijl"; 
    String s2 = "abefghijk"; 

    fun(s1, s2, s1.length()-1, s2.length()-1, 0); 
    System.out.println("maxcount == "+maxcount); 
} 

static void fun(String s1, String s2, int i, int j, int count) 
{ 
    if(i == -1 || j==-1) 
     return; 

    if(s1.charAt(i) == s2.charAt(j)) 
    { 
     if(count+1 > maxcount) 
      maxcount = count+1; 
     fun(s1, s2, i-1, j-1, count+1); 
    } 
    else 
    { 
     fun(s1, s2, i-1, j, 0); 
     fun(s1, s2, i, j-1, 0); 
    } 
} 
} 

Это прекрасно работает. Тем не менее, есть несколько вещей, которые мне не нравится мой код

  1. Использование глобального переменный (статический INT MAXCOUNT) для сравнения разных кадров
  2. Я не думаю, что это реально динамическое программирование или возвраты , так как нижний кадр не , возвращающий, он выводит на более высокий кадр, который затем решает, что с ним делать.

Просьба дать мне свои данные о том, как я могу достичь этого, не используя глобальную переменную и используя обратный трассировку.

PS: Я знаю о других подходах к проблеме, как сохранение матрицы, и делать что-то вроде

M [я] [J] = M [I-1] [J-1] +1 if (str [i] == str [j])

Целью является не решение проблемы, а поиск элегантного рекурсивного/обратного отслеживания.

+0

Возможный дубликат [Серия Common Substring] (http://stackoverflow.com/questions/22319437/longest-common-substring) – Prune

ответ

-1

Возможно, это может быть сделано в Прологе. Ниже приводится код, который я мог бы поставить вниз с помощью с этого поста: Foreach not working in Prolog, http://obvcode.blogspot.in/2008/11/working-with-strings-in-prolog.html и How do I find the longest list in a list of lists?

myrun(S1, S2):- 
    writeln("-------- codes of first string ---------"), 
    string_codes(S1, C1list), 
    writeln(C1list), 

    writeln("-------- codes of second string ---------"), 
    string_codes(S2, C2list), 
    writeln(C2list), 

    writeln("--------- substrings of first --------"), 
    findall(X, sublist(X, C1list), L), 
    writeln(L), 

    writeln("--------- substrings of second --------"), 
    findall(X, sublist(X, C2list), M), 
    writeln(M), 

    writeln("------ codes of common substrings -------"), 
    intersection(L,M, Outl), 
    writeln(Outl), 

    writeln("--------- common strings in one line -------"), 
    maplist(string_codes, Sl, Outl), 
    writeln(Sl), 
    writeln("------ common strings one by one -------"), 
    maplist(writeln, Sl), 

    writeln("------ find longest -------"), 
    longest(Outl, LongestL), 
    writeln(LongestL), 
    string_codes(LongestS, LongestL), 
    writeln(LongestS). 

sublist(S, L) :- 
    append(_, L2, L), 
    append(S, _, L2). 

longest([L], L) :- 
    !. 
longest([H|T], H) :- 
    length(H, N), 
    longest(T, X), 
    length(X, M), 
    N > M, 
    !. 
longest([H|T], X) :- 
    longest(T, X), 
    !. 

Она работает, показывая все шаги: Это преобразование строк кодов, а затем сделать все возможные подстроки от обоих, а затем найти те, которые являются общими и перечислены:

?- myrun("abcdf", "bzcdf"). 
-------- codes of first string --------- 
[97,98,99,100,102] 
-------- codes of second string --------- 
[98,122,99,100,102] 
--------- substrings of first -------- 
[[],[97],[97,98],[97,98,99],[97,98,99,100],[97,98,99,100,102],[],[98],[98,99],[98,99,100],[98,99,100,102],[],[99],[99,100],[99,100,102],[],[100],[100,102],[],[102],[]] 
--------- substrings of second -------- 
[[],[98],[98,122],[98,122,99],[98,122,99,100],[98,122,99,100,102],[],[122],[122,99],[122,99,100],[122,99,100,102],[],[99],[99,100],[99,100,102],[],[100],[100,102],[],[102],[]] 
------ codes of common substrings ------- 
[[],[],[98],[],[99],[99,100],[99,100,102],[],[100],[100,102],[],[102],[]] 
--------- common strings in one line ------- 
[,,b,,c,cd,cdf,,d,df,,f,] 
------ common strings one by one ------- 


b 

c 
cd 
cdf 

d 
df 

f 

------ find longest ------- 
[99,100,102] 
cdf 
true. 

Игнорировать «истину» в конце.

Если пояснительные части удаляются, программа намного короче:

myrun(S1, S2):- 
    string_codes(S1, C1list), 
    string_codes(S2, C2list), 
    findall(X, sublist(X, C1list), L),  
    findall(X, sublist(X, C2list), M), 
    intersection(L,M, Outl), 
    longest(Outl, LongestL), 
    string_codes(LongestS, LongestL), 
    writeln(LongestS). 

sublist(S, L) :- 
    append(_, L2, L), 
    append(S, _, L2). 

longest([L], L) :- 
    !. 
longest([H|T], H) :- 
    length(H, N), 
    longest(T, X), 
    length(X, M), 
    N > M, 
    !. 
longest([H|T], X) :- 
    longest(T, X), 
    !. 


?- myrun("abcdf", "bzcdf"). 
cdf 
true.