Java 检查关键字是否在字符串中

Java 检查关键字是否在字符串中,java,Java,我有一个关键字列表,我希望能够找到一个字符串是否包含这些关键字中的任何一个。现在我得到的解是O(n)。有没有一种更快的方法来进行搜索,而无需循环搜索每个关键字并进行比较/包含 i、 e。 关键词:“猫”、“帽子”、“垫子”、“蝙蝠”、“脂肪”、“坐”、“老鼠”、“帕特”、“富吧”、“富吧” String=“盒子里有一只猫。” 结果是正确的,因为“cat”与“关键字”中的一个单词匹配 编辑: 我想当我说O(n)时,我没有那么清楚。我的意思是O(n),其中n=关键字的数量 k = # of char

我有一个关键字列表,我希望能够找到一个字符串是否包含这些关键字中的任何一个。现在我得到的解是O(n)。有没有一种更快的方法来进行搜索,而无需循环搜索每个关键字并进行比较/包含

i、 e。 关键词:“猫”、“帽子”、“垫子”、“蝙蝠”、“脂肪”、“坐”、“老鼠”、“帕特”、“富吧”、“富吧” String=“盒子里有一只猫。” 结果是正确的,因为“cat”与“关键字”中的一个单词匹配

编辑: 我想当我说O(n)时,我没有那么清楚。我的意思是O(n),其中n=关键字的数量

k = # of chars in sentence
n = # of keywords
m = # of words in sentence
通过对
句子中的单词进行哈希运算,可以获得
O(k+n)
时间复杂度

把句子分成几个词需要
O(k)
。创建哈希集也需要
O(k)
。检查哈希
n
时间需要
n*O(1)=O(n)
,因此总体时间复杂度为
O(k+n)


Edit1:对所有
n
关键字进行哈希运算在技术上是
n*O(k/m)
,其中
k/m
是平均字长。但是,
k/m
不随输入的大小而缩放,因此它仍然给出
O(n)


Edit2:仅供参考,Boyer Moore将匹配任何子字符串,而不仅仅是关键字;例如,“cat”将与“catepillar”匹配。此外,因为它更通用,所以它的运行时间比简单的单词匹配要差,
O(KN)
as@SteveP。他的回答中有一句话

因此,如果您只需要单词匹配,而不需要子字符串匹配,请坚持使用如上所述的哈希。

不确定它是否会找到inO(n)

但是找到元素的解决方案可能是这样的

  List<String>  keywords = new ArrayList<String> (Arrays.asList("cat", "hat", "mat", "bat", "fat", "sat", "rat", "pat", "foo bar", "foo-bar"));
  String search= "There is a cat in the box." ;   
  List<String>  searchWords = new ArrayList<String> (Arrays.asList(search.split(" ")));     
  System.out.println(!Collections.disjoint(keywords,searchWords));
List关键字=新的ArrayList(Arrays.asList(“cat”、“hat”、“mat”、“bat”、“fat”、“sat”、“rat”、“pat”、“foo bar”、“foo bar”);
String search=“盒子里有一只猫。”;
List searchWords=newarraylist(Arrays.asList(search.split(“”));
System.out.println(!Collections.disjoint(关键字,搜索词));
您可以使用,这涉及到对字符串进行预处理,但您无法克服最坏的情况O(KN),其中K是关键字长度的总和,N是字符串的长度。最好的情况当然是次线性的,但你不能有最坏的次线性运行时

请注意,这些比较不是免费的。并不是说你可以比较O(1)中的两个字符串来判断它们是否相等,你必须遍历这些字符。散列可以让您在固定时间内找到需要比较的内容,但没有比这更大的帮助,因为两个不同的字符串可以具有相同的散列。这并不是说哈希不好,它是,但它不会改变最坏情况下的运行时复杂性

最后,您需要比较角色,Boyer Moore提供了一个非常好的方法。当然,如果您使用某种基于散列的构建,您可能能够在摊销的固定时间内排除某些关键字,但这并不能改变一个事实,即在最坏的情况下(以及许多其他情况下),您需要比较字符


还请注意,根据我们对数据的假设,以及我们如何构造索引结构,有可能实现非常好的实际运行时。仅仅因为最坏情况的复杂性不是次线性的,并不意味着实际的运行时不会很快。没有单一的简单或正确的解决方案,这个问题可以通过多种方式解决。当涉及到信息检索时,从来没有一个快速而肮脏的答案可以解决你所有的问题。

你可能不会比O(n)更好,因为这件作品有一个线性的组成部分-你必须以某种形状、形式或方式拖网

考虑使用
集合

  • 添加所有元素的恒定时间(对于N个元素,可以将其摊销为N)
  • 恒定时间寻找存在

public boolean inPhrase(String phrase, String searchWord) {
    Set<String> phraseSet = new HashSet<>();
    // remove the punctuation and split the words on white space.
    for(String s:  phrase.replaceAll("[.,?!;"'], "").split(" ")) {
        phraseSet.add(s);
    }
    return phraseSet.contains(searchWord);
}
公共布尔输入短语(字符串短语、字符串搜索词){
Set phraseSet=新HashSet();
//删除标点符号并在空白处拆分单词。
用于(字符串s:phrase.replaceAll(“[,?!;”],”).split(“”){
短语集。添加(s);
}
返回phraseSet.contains(searchWord);
}
可以尝试使用contains()

获取字符串;字符串passed=“盒子里有一只猫”

使用for循环浏览你的关键词。如果关键字是数组

for(int i = 0; i < keywords.length; i++){
    if(passed.toLowerCase().contains(keywords[i]){
        //set true;
    }else{
        //set false;
    }
}
for(int i=0;i

无论是通过循环还是逐个检查每个单词,我认为你都不会比O(n)好多少。

你怎么可能发现长度为n的字符串中没有一个单词的长度小于O(n)!?一种粗略的方法是检查你的输入是否以“at”或“bar”结尾。如果是这样,请检查它是否以关键字的相应第一部分开始。这很难看,我相信有更适合的算法/数据结构。但再说一次:大O表示法是最坏的情况。最坏的情况总是N。你要找的是大θ,它定义了一个平均的、可能的情况。IO(n)中的n字符串的长度或关键字的长度?@bcorso,字符串的长度绝对是一个因素。@Jeroen Vannevel,Big-O不仅适用于最坏的情况,尽管它最适合最坏的情况。而且,最坏的情况并不总是N。即使采用天真的方法,也不需要N的任何东西就可以发现第一个关键字位于第一个位置。如果他在句子中加逗号会怎么样?比如“有一只猫,它在盒子里。”或者“有一只猫,它在盒子里”@Eddie,如何标记一个句子是偶然的。如果OP对此有问题,他可以作为一个新问题提出来。Boyer Moore字符串搜索算法用于java模式实现。@bcors