在Java中的字符串列表中查找公共子表达式的最有效方法

时间:2012-10-26 11:15:49

标签: java arrays algorithm

我有一个表示包目录的字符串列表。我想迭代列表,找到包相同的字符串的最大部分,然后提取这个子字符串,从原始字符串列表中减去该字符串以获取特定包,以便创建相应的目录。

我在考虑将原始列表创建为静态哈希集,然后使用retainAll方法,将结果存储在新的String中。

这样的事情是最有效的选择,还是有更好的方法呢?

非常感谢

3 个答案:

答案 0 :(得分:1)

这对我有用,在评论中解释

// returns the length of the longest common prefix of all strings in the given array 
public static int longestCommonPrefix(String[] strings) {
    // Null or no contents, return 0
    if (strings == null || strings.length == 0) {
        return 0;
        // only 1 element? return it's length
    } else if (strings.length == 1 && strings[0] != null) {
        return strings[0].length();
        // more than 1
    } else {
        // copy the array and sort it on the lengths of the strings,
        // shortest one first.
        // this will raise a NullPointerException if an array element is null 
        String[] copy = Arrays.copyOf(strings, strings.length);
        Arrays.sort(copy, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.length() - o1.length();
            }
        });
        int result = 0; // init result
        // iterate through every letter of the shortest string
        for (int i = 0; i < copy[0].length(); i++) { 
            // compare the corresponding char of all other strings
            char currenChar = copy[0].charAt(i);
            for (int j = 1; j < strings.length; j++) {                  
                if (currenChar != copy[j].charAt(i)) { // mismatch
                    return result;
                }
            }
            // all match
            result++;
        }
        // done iterating through shortest string, all matched.
        return result;
    }
}

如果更改原始数组不会打扰您,您可以省略行String[] copy = Arrays.copyOf(strings, strings.length);,只需对strings数组进行排序。

要检索文本,请将返回类型更改为String,并在循环内返回类似return copy[0].substring(0, result + 1);的内容,并在方法末尾返回return copy[0];

答案 1 :(得分:0)

如果您只是寻找最常见的一个包,我会执行以下操作:

从列表中获取第一个元素(将其称为参考包)。使用这个包名称,我将遍历列表。对于列表中的每个剩余元素,查看元素是否包含引用包。如果是这样,请转到下一个元素。如果没有通过一个包修改您的参考包(采用aa.bb.cc.serverside并转换为aa.bb.cc)。然后查看当前元素是否包含此新引用包。重复此操作,直到参考包为空或直到元素匹配为止。然后继续查看软件包列表。

这将为您提供最常见的包。通过从列表中的所有元素中删除它来循环回来。

编辑:稍加修改,最好将.保留在包名末尾,以确保包名称完整。

答案 2 :(得分:0)

只需对它们进行排序。公共前缀将首先出现。