2013-12-20 45 views
2

Common Child的编程挑战中,我采取了不同于通用最长公共子串问题的方法。该守则是最长公共子串的方法

#include <cmath> 
#include <cstdio> 
#include <vector> 
#include<string> 
#include <iostream> 
#include <algorithm> 
using namespace std; 

void max(string a,string b,int n) 
{ 
    int count=0,x=-1,prev=0,i,j,k; 
    for(i=0;i<n;i++) 
    { 
     x=-1; 
     for(j=i;j<n;j++) 
     { 
      for(k=x+1;k<n;k++) 
      { 
       if(a[j]==b[k]) 
       { 
        count++; 
        x=k; 
        break; 
       } 
      } 
     } 
     if(prev<count) 
     { 
      prev=count; 
     } 
     count=0;   
    } 
    cout<<prev; 
} 

int main() { 
    string a,b; 
    int n; 
    cin>>a; 
    cin>>b; 
    n=a.length(); 
    max(a,b,n); 
    return 0; 

要小的TestCase我被抽到的解决办法,但我不能够得到解决了较长的。

我所做的是

输入:ABCDEF - 让它成为一个FBDAMN - 让它是B,因为它是插在 代码。输出:2.即。 BD是子字符串。

所以我在这里做的是检查每个 子串的匹配子串,并打印最大的子串。即。 ABCDEF的子字符串, BCDEF,CDEF,DEF,EF,F这表示最外面的循环(循环i)

现在第二个循环匹配字符串ie中的每个字母。它对(1 ... n),(2 ... n),(3 ... n),...,(n)迭代 ,这意味着它从我指定的字母 开始。

现在第三个循环遍历整个字符串B,查看 a [j]是否与B中的任何字母匹配,如果是,则计数增量。

,因为我们只能删除从子信件,而不是把它打乱, 即每个字母应该有两个 串相同的相对顺序,我正在寻找B中的上一封信后发现,使用 X。

空运行会像的例子(数组从0到n-1)

一个= ABCDEF B = fbdamn

当i = 0 - 整个字符串是越来越匹配ABCDEF

x = -1所以k从0到n-1迭代所以,a = f? A = B? A = d? A = A? count = count + 1;所以x被设置为3(a的位置)。 A之后的元素只能在B中出现,因此x = 3。因此k从4迭代到5 b = m? b = n? C = M + C = N? .... ...

现在我们保存之前的计数值,如果它大于计数 之前。因此maxcount = count,然后重置计数为0,并重置 位置x = -1。

i = 1,即字符串= BCDEF k从0到n所以,B = F? B =? count = count + 1 // 变为1 x设置为1(B的位置)k从2到n c = d? C = A C = M + C = N? k从2到n d = d? count = count + 1 //将2 x设置为2 k从3 到n e = a?e = m?e = n? k从3到n f = a?f = m?f = n?那么如果最大计数(prev在 码)大于当前计数,则maxcount = count,reset count = 0,x = -1;那么它对于CDEF,DEF,EF,F就是这样的最大子字符串 因此变成这样2

适用于较短的测试用例,而不适用于较长的测试用例。

测试情况下,它适用于有:

OUDFRMYMAW AWHYFCCMQX

随着输出2

不工作对于

WEWOUCUIDGCGTRMEZEPXZFEJWISRSBBSYXAYDFEJJDLEBVHHKS FDAGCXGKCTKWNECHMRXZWMLRYUCOCZHJRRJBOAJOQJZZVUYXIC

正确的输出是和我的输出是。任何人都可以给我解释一下我在哪里在

+4

我不明白关于这个问题的最后一票:问题是完整的,并且非常有意义。 – dasblinkenlight

回答

4

的问题是,你的算法使用一个天真贪婪方法:它使匹配只要它看到它,之后从未重新考虑其决定,直到它到达下一子。它可以用一个反例,这种贪婪策略不会为LCS工作证明:考虑串

A = "abcd" 
B = "acdb" 

你的算法returns 2因为资金"ab",而最长子是"acd",用3

长度

这两个字符串是仔细构造,以欺骗你的算法产生不正确的结果。您的算法将与初始位置的'a'相匹配,前进到字符串A的第二个字符'b',并将其匹配到字符串B的最后一个位置。此时,您的算法注定要失败:找不到'c''d',因为B的所有字符都已耗尽。它应该做的就好像它可以通过回溯匹配'b'的决定来做得更好。这个问题的答案之一是一个响亮的“是”:如果我们跳过A第二个字符,我们将同时匹配'c''d',为3

一个适当的实施LCS(与DP或正确的结果memoization)这样做是否回溯,而不是指数增长的时间。它是研究和实现的最简单的DP算法之一,所以你应该毫不费力地应用它来解决手头的问题。

6

的一个问题,我预见如下:犯了一个错误:

如果= ABCDEFG和b = ACDEFGB,

现在它将会首先匹配A,那么它会匹配B,但是那么k就会变成6。因此,CDEFG的其他信件将不会被匹配。

因此可能的字符串ACDEFG应该被跳过。

你的代码应该将最大的共同孩子作为CDEFG返回。

编辑:这不是一个最长的公共子串问题,而是一个最长的公共子序列问题。 http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/