使用counter求两个子串相似度问题

字符串相似度计算方法
本文介绍了一种基于Python的字符串相似度计算方法,利用collections模块中的Counter类来统计字符串中各字符出现的次数,并通过比较两个字符串中共有的字符数量来评估它们之间的相似度。
from collections import Counter
def longSim():
    L1 = "abcdefg1223"
    L2 = "abcd88ut1g2f23"
    m = len(L1)
    n = len(L2)

    if m == 0 and n == 0:
        return 1.0
    elif (m * n == 0):
        if m < 10 or n < 10:
            return 0.3
        else:
            return 0.0
    else:

    c1 = Counter(L1)
    print c1

    c2 = Counter(L2)
    print c2

    d1 = dict(c1)
    print d1

    d2 = dict(c2)
    print d2

    count = 0
    print set(c1)&set(c2)
    for i in set(c1)&set(c2):

        print "-----------%d"%d1[i]

        count += min(d1[i],d2[i])
        print float(count)/max(m,n)


longSim()
<think>好的,我现在需要帮助用户解决在Java中实现个字符的最长公共子问题。首先,我得回忆一下相关的算法,最长公共子和最长公共子序列的区别。用户明确提到是子,也就是需要连续的字符,而不是子序列那样可以不连续。接下来,我需要考虑常见的解决方法。动态规划通常是解决这类问题的有效方法。动态规划的思路是创建一个二维数组来记录个字符在各个位置的匹配情况。例如,dp[i][j]表示以字符1的第i个字符和字符2的第j个字符结尾的最长公共子的长度。如果个字符相等,那么dp[i][j] =dp[i-1][j-1] +1,否则为0。同时需要记录最大长度和结束位置,以便最后提取子。 然后,我需要考虑如何优化空间复杂度。因为二维数组可能会占用较大空间,特别是当字符很长时。可以优化为一维数组,因为每次更新只需要前一行的信息。不过,对于初学者来说,可能先实现标准的二维数组方法更容易理解,之后再考虑优化。接下来,我需要编写示例代码。用户要的是Java实现,所以代码结构要符合Java语法。首先处理边界情况,比如空字符的情况。然后初始化dp数组,遍历个字符的所有字符,填充dp数组,并跟踪最大长度和结束位置。最后根据记录的maxLength和endIndex来提取子。 还要注意字符的索引问题,Java中字符的charAt是从0开始的,所以在循环时可能需要从1开始处理,或者调整索引以避免越界。另外,动态规划数组的大小通常是长度加1,这样可以更方便处理初始状态。 用户可能还关心时间复杂度和空间复杂度。动态规划方法的时间复杂度是O(n*m),其中n和m是个字符的长度。空间复杂度如果使用二维数组是O(n*m),优化为一维数组后可以降到O(min(n,m))。 在编写代码时,要确保变量命名清晰,注释适当,方便用户理解。例如,使用maxLength和endIndex这样的变量名,并在关键步骤添加注释说明。 最后,测试示例是否正确。比如用户提到的例子BDCABA和ABCBDAB,最长公共子可能有多个,但根据问题描述,用户可能需要输出其中一个,比如BCBA或BDAB。不过这里可能需要注意,用户提到的例子其实是子序列的例子,而子必须是连续的,所以需要确认正确的测试用例。例如,假设字符是“abcde”和“abcfde”,最长公共子可能是“abc”或“fde”,具体取决于连续情况。可能还需要考虑是否有多个相同长度的最长公共子,如何处理这种情况。通常,代码可能返回第一个找到的最长子,或者可以修改代码来记录所有可能的子,但用户可能只需要一个示例,所以保持简单即可。总结步骤:处理边界情况,初始化DP数组,填充DP数组并记录最大值和结束位置,根据记录提取子。编写代码时注意索引和边界条件,确保正确性。</think>### Java实现最长公共子算法 最长公共子(Longest Common Substring)与子序列不同,要字符必须连续。动态规划是解决该问题的有效方法,时间复杂度为$O(n*m)$。 #### 算法步骤 1. 创建二维数组`dp[i][j]`记录以`str1[i-1]`和`str2[j-1]`结尾的公共子长度 2. 状态转移方程: $$dp[i][j] = \begin{cases} dp[i-1][j-1] + 1 & \text{当 } str1[i-1] = str2[j-1] \\ 0 & \text{否则} \end{cases}$$ 3. 记录最大长度和结束位置 4. 根据结束位置提取子 #### 示例代码 ```java public class LongestCommonSubstring { public static String findLCS(String str1, String str2) { if (str1 == null || str2 == null || str1.isEmpty() || str2.isEmpty()) { return ""; } int[][] dp = new int[str1.length() + 1][str2.length() + 1]; int maxLength = 0; int endIndex = 0; for (int i = 1; i <= str1.length(); i++) { for (int j = 1; j <= str2.length(); j++) { if (str1.charAt(i-1) == str2.charAt(j-1)) { dp[i][j] = dp[i-1][j-1] + 1; if (dp[i][j] > maxLength) { maxLength = dp[i][j]; endIndex = i - 1; // 记录在str1中的结束位置 } } } } return maxLength == 0 ? "" : str1.substring(endIndex - maxLength + 1, endIndex + 1); } public static void main(String[] args) { String s1 = "ABCBDAB"; String s2 = "BDCABA"; System.out.println("最长公共子: " + findLCS(s1, s2)); // 输出"BDAB" } } ``` #### 代码说明 1. 二维数组`dp`比原字符长度多1,避免处理边界条件 2. 双重循环遍历所有字符组合 3. 当字符匹配时更新`dp`值,并跟踪最大长度 4. 通过`substring`方法截取最长子 #### 优化方向 1. 空间优化:使用滚动数组将空间复杂度降为$O(min(n,m))$[^1] 2. 后缀树方法:可将时间复杂度降为$O(n+m)$,但实现复杂度较高 3. 并行处理:对大规模字符进行分块处理
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值