求最大公共字符串
代码:
def LCS_str(s1, s2):
# 求2个字符串的最大公共字符串
# 求对角线上的
arr = [[0 for i in range(len(s2) + 1)] for j in range(len(s1) + 1)]
print(arr)
max = 0
p = 0
for i in range(len(s1)):
for j in range(len(s2)):
if s1[i] == s2[j]:
arr[i][j] = arr[i - 1][j - 1] + 1
if arr[i][j] > max1:
max = arr[i][j]
p = i + 1
print(arr)
return s1[p - max:p], max
print(LCS_str('abcdfga', 'abdfg'))
思路:根据2个字符串的长度,构造对应的矩阵,来记录2个字符串每个字符的匹配情况。
如果匹配,对应位置a[i][j]的值为左上角的值加1,max记录最大公共字符串的长度,p记录最大公共字符串末尾位置的后一个位置。
函数返回最大公共字符串及其长度
求最大公共子序列
子序列:某个序列的子序列指从原序列中不破坏顺序地任意除去若干个字符后形成的序列。
import numpy
def find_lcseque(s1, s2):
# 生成字符串长度加1的0矩阵,m用来保存对应位置匹配的结果
m = [ [ 0 for x in range(len(s2)+1) ] for y in range(len(s1)+1) ]
# d用来记录转移方向
d = [ [ None for x in range(len(s2)+1) ] for y in range(len(s1)+1) ]
for p1 in range(len(s1)):
for p2 in range(len(s2)):
if s1[p1] == s2[p2]: # 字符匹配成功,则该位置的值为左上方的值加1
m[p1 + 1][p2 + 1] = m[p1][p2] + 1
d[p1 + 1][p2 + 1] = 'ok'
elif m[p1 + 1][p2] > m[p1][p2 + 1]:# 左值大于上值,则该位置的值为左值,并标记回溯时的方向
m[p1 + 1][p2 + 1] = m[p1 + 1][p2]
d[p1 + 1][p2 + 1] = 'left'
else: # 上值大于左值,则该位置的值为上值,并标记方向up
m[p1 + 1][p2 + 1] = m[p1][p2 + 1]
d[p1 + 1][p2 + 1] = 'up'
print(numpy.array(m))
print(numpy.array(d))
s = []
while m[p1][p2]: # 不为None时
c = d[p1][p2]
if c == 'ok': # 匹配成功,插入该字符,并向左上角找下一个
s.append(s1[p1 - 1])
p1 -= 1
p2 -= 1
if c == 'left':
# 根据标记,向左找下一个
p2 -= 1
if c == 'up': # 根据标记,向上找下一个
p1 -= 1
s.reverse()
return ''.join(s)
print(find_lcseque('abcdfga', 'abdfgb'))
思路:生成2个矩阵,一个矩阵记录字符串匹配情况,一个矩阵记录转移方向。
如果匹配,对应矩阵位置的值为左上方加1,不匹配则取上方或左上方的最大值。
其他的看注释
def loadData(filename):
import jieba
txt = open(filename).read()
words = jieba.lcut(txt) #读取中文字符
return words
这可以拿来对比文章相似度,引入jieba库即可(太大的不要尝试,容易死机)。