XZ_iOS之LD算法实现字符串相似度的比较

目录

思路

OC的代码实现:

Swift版的代码实现:


例如:

文字段1:“初始化第一列”和 文字段2:“初始化第一行”,这两段文字的相似程序比较,可以看出这两句只要一个字不同,那相似程度就是  1- 1/6 = 5/6 ≈ 0.833333。

相似程度的计算公式就是:相似程度(百分比) = 1 - (不同的字符个数)/MAX(文字1,文字2)

注意:不同的字符个数,指的是同一个位置上,即相同下表。

思路

1、计算编辑距离:

       1>因为OC不能定义确定长度的二维数组,所以,我先定义了一个 len1 * len2 的二维数组;

       2>通过LD算法,计算编辑距离;

 2、通过编辑距离,计算相似度。

OC的代码实现:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSString *str1 = @"GGATCGA";// @"GGATCGA"; @"初始化第一列";
    NSString *str2 = @"GAATTCAGTTA";//@"GAATTCAGTTA"; @"初始化第一行";
    
    CGFloat similar = [self calSimilar:str1 str2:str2];
    NSLog(@"%f",similar);
}

//  计算编辑距离
- (CGFloat)calDistance:(NSString *)str1 str2:(NSString *)str2 {
    
    int len1 = (int)str1.length;
    int len2 = (int)str2.length;
    
    if (len1 == 0) { return len2;}
    if (len2 == 0) { return len1;}
    
    // 初始化一个len1 * len2 的二维数组,第一行和第一列不再改变
    NSMutableArray *d = [NSMutableArray array];
    for (int i = 0; i <= len1; i++) { // i = 0,初始化第一列
        NSMutableArray *array = [NSMutableArray array];
        for (int j = 0; j <= len2; j++) { // j = 0,初始化第一行
            [array addObject:@(j)];
        }
        [d addObject:array];
    }
    
    NSLog(@"初始化的二维数组:%@",d);
    
    int eq = 0;
    NSString *char1, *char2;

    for (int i = 1; i <= len1; i++) {
        char1 = [str1 substringWithRange:NSMakeRange(i-1, 1)];

        for (int j = 1; j <= len2; j++) {
            char2 = [str2 substringWithRange:NSMakeRange(j-1, 1)];

            if ([char1 isEqualToString: char2]) {
                eq = 0;
            }else {
                eq = 1;
            }
            d[i][j] = @(MIN(MIN([d[i-1][j] intValue] + 1, [d[i][j-1] intValue]+1),[d[i-1][j-1] intValue] + eq));
        }
    }
    
    NSLog(@"\n\n\n ====== %@",d);
    return [d[len1][len2] floatValue];
}

// 计算相似度
- (CGFloat)calSimilar:(NSString *)str1 str2:(NSString *)str2 {
    if (str1 == NULL || str2 == NULL || str1.length == 0 || str2.length == 0) {
        return 0;
    }
    
    CGFloat distance = [self calDistance: str1 str2: str2];
    NSLog(@"\n 计算相似度:%f",distance);
    NSLog(@"\n str1.length:%lu",(unsigned long)str1.length);
    NSLog(@"\n str2.length:%lu",(unsigned long)str2.length);
    
    NSLog(@"\n MAX:%lu",(unsigned long)MAX(str1.length, str2.length));
    
    return 1 - distance / MAX(str1.length, str2.length);
}

初始化完的数组打印结果是:

计算编辑距离的打印结果是:

计算完编辑距离的二维数组(上图中)的最后一个数字  5 就是编辑距离了。

计算结果打印:

XZ_iOS之LD算法实现字符串相似度的比较_第1张图片

Swift版的代码实现:

override func viewDidLoad() {
        super.viewDidLoad()
        
        // "GGATCGA" "初始化第一列"
        let str1 = "初始化第一列"
        // "GAATTCAGTTA" "初始化第一行"
        let str2 = "初始化第一行"
        
        let similar = calSimilar(str1: str1, str2: str2)
        
        print("\n similar",similar)
    }
    
    //  计算编辑距离
    func calDistance(str1: String,str2: String) -> Float {
        let len1 = str1.count
        let len2 = str2.count
        
        if len1 == 0 { return Float(len2) }
        if len2 == 0 { return Float(len1) }
        
        // 初始化一个len1 * len2 的二维数组
        var d = [Array]()
        
        for _ in 0...len1 {
            
            var array = [Int]()
            
            for j in 0...len2 {
                array.append(j)
            }
            d.append(array)
        }
        
        print("初始化的二维数组:",d)
        
        var eq = 0
        var char1: String, char2: String
        
        for i in 1...len1 {
            char1 = (str1 as NSString).substring(with: NSRange(location: i-1, length: 1))
            for j in 1...len2 {
                char2 = (str2 as NSString).substring(with: NSRange(location: j-1, length: 1))
                
                if char1 == char2 {
                    eq = 0
                }else {
                    eq = 1
                }
                d[i][j] = min(min(d[i-1][j] + 1, d[i][j-1] + 1),d[i-1][j-1] + eq)
            }
        }
        
        print("\n 计算编辑距离:",d)
        return Float(d[len1][len2])
    }
    
    // 计算相似度
    func calSimilar(str1: String?, str2: String?) -> Float {
       guard let str1 = str1,
        let str2 = str2
        else { return 0.0 }
        
        let distance = calDistance(str1: str1, str2: str2)
        print("\n distance", distance)
        
        return 1 - distance / Float(max(str1.count, str2.count))
    }

GitHub代码

参考文章

C代码实现 https://blog.csdn.net/majinfei/article/details/16979049

Java代码实现 https://blog.csdn.net/YZCSzhiYZTY/article/details/46650621

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