我想创建一个强力算法来找到2个字符串之间最大的公共子序列,但我很难以算法的形式列举所有可能性。
我不想要一个动态的编程答案,因为奇怪的是我设法解决了这个问题(你会认为蛮力方法会更容易)。请使用伪代码,因为我更喜欢理解它并自己编写。
答案 0 :(得分:4)
它与DP减去记忆部分几乎相同。
LCS(s1, s2, i, j):
if(i == -1 || j == -1)
return 0
if(s1[i] == s2[j])
return 1 + LCS(s1, s2, i-1, j-1)
return max(LCS(s1, s2, i-1, j), LCS(s1, s2, i, j-1))
我们的想法是,如果我们有两个字符串s1和s2,其中s1在i处结束,而s2在j处结束,则LCS为:
时间复杂度显然是指数级的。
答案 1 :(得分:4)
我喜欢@ turingcomplete的答案,但它并不是真正的蛮力,因为它实际上并没有列举所有候选解决方案。例如,如果字符串是" ABCDE"和#34; XBCDY",递归方法不会测试" ABC"与" XBC"因为测试" A"与" X"会失败的。尽管如此,你是否想要将其视为一个独特的候选人,这是一种意见问题。事实上,你可以争辩说" ABC"与" ABCDY"也是一个有效的候选人,并且由于长度差异而立即失败。您可以在下面的代码中添加单独的LA
和LB
,以完全枚举这些候选人。
for L = min(A.length, B.length) to 1
{
for iA = 0 to A.length - L - 1
{
for iB = 0 to B.length - L - 1
{
for i = 0 to L - 1
{
if(A[iA] != B[iB])
{
match failed;
}
}
if match didn't fail, then
A[iA..iA+L] and B[iB..iB+L] are a maximal common substring
}
}
}
no common substring
答案 2 :(得分:0)
这是一个Java方法,用于存储/列出ArrayList中给定字符串的所有子序列。
递归解决方案:
void subSeq(String s, ArrayList<String> h)
{
int n = h.size();
for(int i=0;i<n;i++)
h.add(h.get(i) + s.charAt(0));
if(s.length()>1)
subSeq(s.substring(1,s.length()),h);
}
首次调用subSeq()时,ArrayList应该包含一个空字符串。
我们已经知道每个字符都可以
1)出现
或
2)不会出现在任何子序列中。
因此,我们保持ArrayList中的所有字符串不变(上面的情况2)。
此外,我们添加(到ArrayList)字符串,这些字符串是
与ArrayList中已经存在的字符串的串联
字符串的第一个字符(上述情况1)。
这涵盖(解决了)我们问题的上述两种情况。
征服第一个字符后,我们递归调用该方法
再次使用上述字符串的子字符串(不包含第一个字符)
,该子字符串将被发送以获取其第一个字符
被征服了。
这将一直持续到我们收到长度为1的字符串。
迭代解决方案:
ArrayList<String> subSeq(String s)
{
ArrayList<String> h = new ArrayList<String>();
h.add("");
int n = s.length();
int l;
for(int i=0;i<n;i++)
{
l = h.size();
for(int j=0;j<l;j++)
h.add( h.get(j) + s.charAt(i));
}
return h;
}