-1

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

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

2 喝

16水瓶

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

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

因此,我们将不胜感激找到最长关键字的任何帮助。谢谢。

4

2 回答 2

0

如果可以从较小的关键字构建关键字,那么您对有效代码所做的一切就是首先检查较长的关键字。请注意:我根本没有测试这个,我想我已经在这个问题上做了足够的工作!如果这对您有帮助,请不要忘记投票+接受。

IE

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;
    }
}
于 2012-11-16T19:25:50.910 回答
0

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

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

drank
water bottle
    bottle
    water

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

创建树需要一些工作。

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

clean water bottle
    clean bottle
        clean
    water bottle
        bottle
        water    
于 2012-11-16T20:02:46.130 回答