Python 香草巨蟒-(剽窃检查器)如何检测原始句子中相同的单词?

Python 香草巨蟒-(剽窃检查器)如何检测原始句子中相同的单词?,python,Python,我想用python制作一个简单的剽窃检查器。在python中不使用外部libs 因此,如果相同的单词连续出现4次以上,我想打印输出(连续的相同单词) 我尝试了下面的代码。 但它会显示每个相同的单词,即使这些单词的连续相同次数不少于4次 b1='我想大阪市只是一个没有灵魂的城市,这显然很奇怪。'split('') a1=“我想所有这些没有意义的时间,都是因为我认为大阪市是一个巨大的、没有灵魂的城市,这显然是很奇怪的。”斯普利特(“”) #预期结果 #[“大阪是一座没有灵魂的城市,这显然很奇怪”]

我想用python制作一个简单的剽窃检查器。在python中不使用外部libs

因此,如果相同的单词连续出现4次以上,我想打印输出(连续的相同单词)

我尝试了下面的代码。 但它会显示每个相同的单词,即使这些单词的连续相同次数不少于4次

b1='我想大阪市只是一个没有灵魂的城市,这显然很奇怪。'split('')
a1=“我想所有这些没有意义的时间,都是因为我认为大阪市是一个巨大的、没有灵魂的城市,这显然是很奇怪的。”斯普利特(“”)
#预期结果
#[“大阪是一座没有灵魂的城市,这显然很奇怪”]
temp1=[]
对于b1中的b:
对于a1中的a:
如果b==a:
temp1.追加(b)
如果len(temp1)>=4:
打印(''.join(temp1))
其他:
打印('='')
然而结果是

i guess that osaka city city is is a souless city city it is is obviousl
y
i guess that osaka city city is is a souless city city it is is obviousl
y
i guess that osaka city city is is a souless city city it is is obviousl
y weird
而且。。。这就是我想做的

#####示例;
#输入
a='你好,我叫大阪,今天我了解了摩奇
只是一堆雪人的屎
b=‘你好,我的名字叫雷恩,胡说,曼恩昨天我听说卡祖只是个狗屎雪人’
#预期产量
[“你好,我的名字是”,“只是一个狗屎雪人”]

你把
a1
中的每个单词都记下来,然后与
b1
中的每个单词进行比较。所有匹配的单词都添加到
temp1
。但是你从不检查单词的序列。这就是为什么在
b1
中会出现
a1
的所有单词

这里有一个比较序列的简单方法:取
a1
b1
中的每两个索引,并在字符匹配时尝试前进。如果找到4个或更多匹配字符,请输出以下字符:

B='i guess that osaka city is just a souless city it is obviously weird'.split(' ')
A='all of the meaning less time i guess thinking that osaka city is huge a souless city it is obviously weird'.split(' ')

for i in range(len(A)):
    for j in range(len(B)):
        m, n = i, j
        while m<len(A) and n<len(B) and A[m] == B[n]:
            m, n = m+1, n+1
        if m-i >= 4:
            print((i, j), A[i:m])
输出

(9, 2) ['that', 'osaka', 'city', 'is']
(14, 7) ['a', 'souless', 'city', 'it', 'is', 'obviously', 'weird']
(15, 8) ['souless', 'city', 'it', 'is', 'obviously', 'weird']
(16, 9) ['city', 'it', 'is', 'obviously', 'weird']
(17, 10) ['it', 'is', 'obviously', 'weird']
你会得到一些垃圾,因为如果
['a','souless','city','it','is','scientive','wird']
是从
(14,7)
开始的最长匹配,我们知道从
(15,8)
开始的列表也会是匹配的。让我们添加一个
exclude
集来删除这些子列表:

exclude = set()
for i in range(len(A)):
    for j in range(len(B)):
        if (i,j) in exclude:
            exclude.remove((i,j))
            continue
        m, n = i, j
        while m<len(A) and n<len(B) and A[m] == B[n]:
            m, n = m+1, n+1
        if m-i >= 4:
            print((i, j), A[i:m])
            exclude.update((i+k, j+k) for k in range(1, m-i))
            print ("exclude = ", exclude)
这种方法可行,但速度非常慢:时间复杂度为O(| A |*| B |*最长匹配)。使用以下方法可以省去一些检查:为列表| B |构建一个字典
word->[positions]
,以避免为
a
的每个单词重新检查
B
中的所有索引:

positions_by_word_in_B = {}
for j, word in enumerate(B):
    positions_by_word_in_B.setdefault(word, []).append(j)
输出:

(9, 2) ['that', 'osaka', 'city', 'is']
exclude =  {(12, 5), (11, 4), (10, 3)}
(14, 7) ['a', 'souless', 'city', 'it', 'is', 'obviously', 'weird']
exclude =  {(20, 13), (16, 9), (17, 10), (15, 8), (19, 12), (18, 11)}
{'i': [0], 'guess': [1], 'that': [2], 'osaka': [3], 'city': [4, 9], 'is': [5, 11], 'just': [6], 'a': [7], 'souless': [8], 'it': [10], 'obviously': [12], 'weird'
: [13]}
主循环变为:

for i in range(len(A)):
    for j in positions_by_word_in_B.get(A[i], []):
        # all positions of A[i] in B, maybe none
时间复杂度下降到O(| B |+| A |*|在B |*最长匹配中A的最大出现次数)。您还可以在len(A)-4而不是len(A)-1处停止迭代

如果你想检查一大套文件是否有剽窃行为,这可能还是太慢了

for i in range(len(A)):
    for j in positions_by_word_in_B.get(A[i], []):
        # all positions of A[i] in B, maybe none