【问题标题】:search string for longest keyword最长关键字的搜索字符串
【发布时间】:2012-11-16 19:04:26
【问题描述】:

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

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

喝了两杯

16水瓶

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

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

因此,我们将非常感谢您在查找最长关键字方面的任何帮助。谢谢。

【问题讨论】:

  • 什么意思,要找最大的关键字?
  • 最好发布一些代码并准确显示它没有做什么。
  • @AlanKrueger 我的代码还不能正常工作,我不知道它会有多少用处。我愿意使用任何数据结构,我只是认为 trie 的结构最适合逐字逐句。
  • Pattern / Matcher 如何在您的文档中搜索模式/关键字?
  • 如果您的大型文档有很多不同的关键字,请考虑使用 SuffixTrees / SuffixArrays(我只是为您指出不同的方向进行调查)

标签: java string algorithm data-structures trie


【解决方案1】:

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

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

drank
water bottle
    bottle
    water

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

创建树需要一些工作。

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

clean water bottle
    clean bottle
        clean
    water bottle
        bottle
        water    

【讨论】:

  • 我想到了这个,但问题是,如果clean water bottle 不是关键字怎么办
  • 我不确定我是否理解您的问题。我制作了“干净的水瓶”来展示您可以在排序树中拥有多个级别的关键字。您的排序树将只包含您想要的关键字。
  • 换句话说,clean bottlewater bottlebottle 都是单词。那么bottle 会是两者的孩子吗?但是,如果您找到clean bottle,则不要在water bottle 下搜索bottle... 这会变得非常复杂。 I am one manam oneI am a canaryam aam...
  • “瓶子”这个词是“干净的瓶子”或“水瓶”的子代。是的,它可能会变得复杂,这就是为什么我在回答中说设置排序树会有点工作。
【解决方案2】:

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

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;
    }
}

【讨论】:

  • 我很确定这段代码可以找到文档中最长的单词(是的,它只是一个字符串),我正在寻找文档中的关键字,我在数据中有结构(结构类型可以根据需要改变)。所以,如果我的关键字是“水”、“瓶子”、“喝”和“水瓶”,而我的文档是“我从我的水瓶里喝了”,我想找到“喝”的索引( 2)和“水瓶”(16)。
  • @user1535846:我将答案编辑为可以回答您实际问题的内容。看看
猜你喜欢
  • 2014-06-03
  • 1970-01-01
  • 2019-03-13
  • 2021-12-23
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
相关资源
最近更新 更多