我设计了一个算法来找到最长的公共子序列。这些是步骤:
选择第一个字符串中的第一个字母。
在第二个字符串中查找它,如果找到,将该字母添加到
common_subsequence
并将其位置存储在 中index
,否则将 的长度common_subsequence
与 的长度进行比较lcs
,如果更大,则将其值分配给lcs
。返回第一个字符串并选择下一个字母并再次重复上一步,但这一次从第一个
index
字母开始搜索重复此过程,直到第一个字符串中没有要选择的字母。最后的值
lcs
是最长公共子序列。
这是一个例子:
</p>
X=A, B, C, B, D, A, B
Y=B, D, C, A, B, A
选择A
第一个字符串。在 中
寻找。
现在第二个字符串中有一个,将其附加到.
返回到第一个字符串并选择下一个字母. 这次从 的位置开始在第二个字符串中查找。
有一个之后,所以将 B 附加到.
现在选择第一个字符串中的下一个字母. 第二个字符串中没有旁边。所以将 common_subsequence 的值赋值给,因为它的长度大于. 重复前面的步骤,直到到达第一个字符串的末尾。最终的价值A
Y
A
common_subsequence
B
B
A
B
A
common_subsequence
C
C
B
lcs
lcs
lcs
是最长公共子序列。
该算法的复杂度为 theta(n*m)。这是我的实现:
第一种算法:
import time
def lcs(xstr, ystr):
if not (xstr and ystr): return # if string is empty
lcs = [''] # longest common subsequence
lcslen = 0 # length of longest common subsequence so far
for i in xrange(len(xstr)):
cs = '' # common subsequence
start = 0 # start position in ystr
for item in xstr[i:]:
index = ystr.find(item, start) # position at the common letter
if index != -1: # if common letter has found
cs += item # add common letter to the cs
start = index + 1
if index == len(ystr) - 1: break # if reached end of the ystr
# update lcs and lcslen if found better cs
if len(cs) > lcslen: lcs, lcslen = [cs], len(cs)
elif len(cs) == lcslen: lcs.append(cs)
return lcs
file1 = open('/home/saji/file1')
file2 = open('/home/saji/file2')
xstr = file1.read()
ystr = file2.read()
start = time.time()
lcss = lcs(xstr, ystr)
elapsed = (time.time() - start)
print elapsed
使用哈希表的相同算法:
import time
from collections import defaultdict
def lcs(xstr, ystr):
if not (xstr and ystr): return # if strings are empty
lcs = [''] # longest common subsequence
lcslen = 0 # length of longest common subsequence so far
location = defaultdict(list) # keeps track of items in the ystr
i = 0
for k in ystr:
location[k].append(i)
i += 1
for i in xrange(len(xstr)):
cs = '' # common subsequence
index = -1
reached_index = defaultdict(int)
for item in xstr[i:]:
for new_index in location[item][reached_index[item]:]:
reached_index[item] += 1
if index < new_index:
cs += item # add item to the cs
index = new_index
break
if index == len(ystr) - 1: break # if reached end of the ystr
# update lcs and lcslen if found better cs
if len(cs) > lcslen: lcs, lcslen = [cs], len(cs)
elif len(cs) == lcslen: lcs.append(cs)
return lcs
file1 = open('/home/saji/file1')
file2 = open('/home/saji/file2')
xstr = file1.read()
ystr = file2.read()
start = time.time()
lcss = lcs(xstr, ystr)
elapsed = (time.time() - start)
print elapsed