字符串按相似度分组

相关代码已经上传GitHub : https://github.com/EricLi404/go-utils

0x00 概述

在做在做反垃圾账号业务的时候,检测发现有几十名用户都在某个IP上有过行为打点。

# 原始数据
꧁❥?➦SAMI?MMS➣?❥꧂
꧁❥?➦Ⓜ️AHI?MMS➣?❥꧂..
jgcch7b?V?O?I?
2kc7fd7?V?O?I?
꧁❥?➦VIDYA?MMS➣?❥꧂
RcR?Raden??F
RcR?Raden?B
꧁❥?➦RESMA?MMS➣?❥꧂
Sanny8_star197
꧁❥?PARI?MMS➣?❥꧂
❁════❃MAHAKAL❃══7══❁
꧁❥?BIPASHA?MMS➣?❥꧂
.꧁❥?ISRAT?MMS?꧂
ek8660?V?O?I? 
a8h9163?V?O?I?
꧁❥?➦NIRA?➣?❥꧂
꧁❥?PARINEETI?MMS?꧂
RcR?Raden?J
dem3ba2?V?O?I?
ggk5b27?V?O?I?
?RcR?Raden??

可以很明显的感知到其中部分账号存在一定的相似性,现需要将这几十名用户按相似性分为若干组,因此提出了一种基莱文斯坦距离和并查集结构的算法,来实现将一组字符串按相似度提取出若干不重复组的功能。

0x01 理论基础

莱文斯坦距离

Wikipedia:
莱文斯坦距离,又称Levenshtein距离,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。允许的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如将kitten一字转成sitting:

  1. sitten (k→s)
  2. sittin (e→i)
  3. sitting (→g)

则两者之间莱文斯坦距离为3.
俄罗斯科学家弗拉基米尔·莱文斯坦在1965年提出这个概念。

其用途主要有 DNA分析、拼写检查、语音辨识、抄袭侦测 。

并查集

Wikipedia:
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

关于并查集的应用,有个经典的朋友圈问题

0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 10个人,其中 [0,1], [0, 4], [1, 2], [1, 3], [5, 6], [6, 7], [7, 5], [8, 9] 互为朋友,求该10个人中有几个朋友圈(二度以内朋友)。

计算方式如下:

  1. 首先列出所有的用户,然后给每个用户都分为单独的一组
0 1 2 3 4 5 6 7 8 9
A B C D E F G H I J
  1. 然后遍历一度朋友关系[0,1], [0, 4], [1, 2], [1, 3], [5, 6], [6, 7], [7, 5], [8, 9] ,将每组一度关系更新为同一组(将一度关系后者的组更新为前者的组):

[0,1]

0 1 2 3 4 5 6 7 8 9
A A C D E F G H I J

[0, 4]

0 1 2 3 4 5 6 7 8 9
A A C D A F G H I J

[1, 2]

0 1 2 3 4 5 6 7 8 9
A A A D A F G H I J

[1, 3]

0 1 2 3 4 5 6 7 8 9
A A A A A F G H I J

[5, 6]

0 1 2 3 4 5 6 7 8 9
A A A A A F F H I J

[6, 7]

0 1 2 3 4 5 6 7 8 9
A A A A A F F F I J

[7, 5]

0 1 2 3 4 5 6 7 8 9
A A A A A F F F I J

[8, 9]

0 1 2 3 4 5 6 7 8 9
A A A A A F F F I I
  1. 至此,朋友圈已分出,也即
    • [0,1,2,3,4] 为一个朋友圈
    • [5,6,7] 为一个朋友圈
    • [8,9] 为一个朋友圈

0x02 main

  1. 基于莱文斯坦距离计算两个字符串之间的相似度
公式为: 
Similarity(str1,str2) = Levenshtein(str1,str2)*2 / len(str1) + len(str2)

  1. 将莱文斯坦距离小于阈值的两个字符串记为连通(类似于朋友圈问题中的一度朋友), 得到如下列表:
str1 str2 Similarity
꧁❥?➦SAMI?MMS➣?❥꧂ ꧁❥?➦Ⓜ️AHI?MMS➣?❥꧂… 0.123457
kcfd?V?O?I? ah?V?O?I? 0.181818
RcR?Raden?B RcR?Raden?J 0.176471
RcR?Raden?B ?RcR?Raden?? 0.146341
ah?V?O?I? demba?V?O?I? 0.222222
꧁❥?➦NIRA?➣?❥꧂ ꧁❥?PARINEETI?MMS?꧂ 0.358209
RcR?Raden?J ?RcR?Raden?? 0.195122
demba?V?O?I? ggkb?V?O?I? 0.170213
  1. 利用并查集将字符串分组,得到以下分组情况
꧁❥?BIPASHA?MMS➣?❥꧂
꧁❥?➦SAMI?MMS➣?❥꧂
.꧁❥?ISRAT?MMS?꧂
꧁❥?➦Ⓜ️AHI?MMS➣?❥꧂..
꧁❥?➦VIDYA?MMS➣?❥꧂
꧁❥?➦RESMA?MMS➣?❥꧂
꧁❥?PARI?MMS➣?❥꧂
꧁❥?➦NIRA?➣?❥꧂
꧁❥?PARINEETI?MMS?꧂

RcR?Raden??F
RcR?Raden?B
RcR?Raden?J
?RcR?Raden??

jgcchb?V?O?I?
kcfd?V?O?I?
ek?V?O?I? 
ah?V?O?I?
demba?V?O?I?
ggkb?V?O?I?

Sanny8_star197

❁════❃MAHAKAL❃══7══❁

0x03 GitHub

相关代码已经上传Github : https://github.com/EricLi404/go-utils

你可能感兴趣的:(Golang,算法)