搜索最长关键字的字符串

时间:2012-11-16 19:04:27

标签: java string algorithm data-structures trie

我正在使用java,并且有一个大型的(~15000)关键字(字符串)集合,并且我有一个定期包含这些关键字的文档(字符串)。

我想找到文档中每次使用关键字的索引,优先选择较长的关键字(字符数最多的关键字)。例如,如果我的关键字是“水”,“瓶子”,“喝水”和“水瓶”,而我的文件是“我从我的水瓶中喝了”,我希望得到以下结果:

2喝了

16个水瓶

我最初的尝试是使用trie,逐个字符地浏览文档,每当子字符串与关键字匹配时,记录初始索引。然而,一些关键字是较长关键字的前缀(例如,“水”和“水瓶”),并且代码永远不会找到更长的关键字,因为它会记录“水”的索引,然后重新开始。

如果重要,关键字可能包含小写字母,大写字母,空格,连字符和撇号(以及大写字母)。

因此,我们非常感谢您寻找最长关键字的任何帮助。感谢。

2 个答案:

答案 0 :(得分:0)

如果关键字可以通过较小的关键字构建,那么您所使用的代码就是检查较长的关键字。请注意:我根本没有测试过,我想我已经把足够的工作放到这个问题上了!如果这有助于你不要忘记upvote + accept。

即。

import java.util.TreeSet;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.Iterator;

public class KeywordSearcher {
    private TreeSet<String> ts;

    public KeywordSearcher() {
    ts = new TreeSet<String>(new Comparator<String>() {
    // Sort all the keywords by length, largest first
        public int compare(String arg0, String arg1) {
            if(arg0.length() > arg1.length()) return -1;
            if(arg0.length() == arg1.length()) return 0;
            return 1;
        }});
    }

    public void addKeyword(String s) {
        ts.add(s);
    }

    private LinkedList<Integer> findKeyword(String document, String s) {
        int start = 0;
        int index;
        LinkedList<Integer> indexes = new LinkedList<Integer>();        

        while(true) {
            index = document.indexOf(s, start);
            if (index == -1) break;
            indexes.add(index);
            start = index + s.length();
        }

        return indexes;
    }

    public HashMap<String, LinkedList<Integer>> findAllKeywords(String document) {
        Iterator<String> is = ts.iterator();
        HashMap<String, LinkedList<Integer>> allIndices = new HashMap<String, LinkedList<Integer>>();

        while(is.hasNext()) {
            String nextKeyword = is.next();
        // See if we found a larger keyword, if we did already, skip this keyword
        boolean foundIt = false;
        for (String key : allIndices.keySet()) {
                if(key.contains(nextKeyword)) {
                    foundIt = true;
                    break;
                }
        }
            if (foundIt) continue;

            // We didn't find the larger keyword, look for the smaller keyword
            LinkedList<Integer> indexes = findKeyword(document, nextKeyword);

            if (indexes.size() > 0) allIndices.put(nextKeyword, indexes);
        }

        return allIndices;
    }
}

答案 1 :(得分:0)

如果我理解正确,如果您在文档中找到“水瓶”,则想跳过搜索“水”。这意味着您的关键字会出现某种树状结构。

我的建议是将您的关键字排列在这样的排序树上:

drank
water bottle
    bottle
    water

在您的代码中,您将首先搜索根目录中的术语(“喝水”和“水瓶”)。如果“水瓶”的匹配数量为零,那么您将导航到下一级别并搜索这些术语(“瓶子”和“水”)。

创建树需要一些工作。

但是使用这种树结构,你可以有多个复合词。

clean water bottle
    clean bottle
        clean
    water bottle
        bottle
        water