【问题标题】:How do I find any word that contains all the given characters at least once如何找到至少一次包含所有给定字符的任何单词
【发布时间】:2012-05-13 19:36:11
【问题描述】:

我正在使用此代码

                   while((dictionaryWord = br_.readLine()) != null) 
            {
                if(dictionaryWord.matches("^"+word.replace("*" , "." )+"$"))
                {   
                    incrementCounter();
                    System.out.println(dictionaryWord);
                }
            }

预期目标:word = dgo

输出:狗、神、教条 megalogdon 等......

【问题讨论】:

  • 如果输入是“好”怎么办。 “狗”应该在输出中吗?
  • 会不会有重音字符,或者Basic Multilingual Plane之外的字符?
  • @MarkByers 是的,只要每个角色至少出现一次
  • @MarkByers 只有英文字母的 26 个字母
  • 我确信有一个正则表达式可以做到这一点,但你总是可以indexOfcontains 循环遍历所需单词中的所有chars

标签: java


【解决方案1】:

您可以在word 中构建所有字符的Set<Character>,并对其进行迭代。如果一个字符不在dictionaryWord 中,则dictionaryWord 不适合。仅当全部出现时 - 打印 dictionaryWord

    String word = "dog";
    String  dictionaryWord;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    while((dictionaryWord = br.readLine()) != null)  {
        Set<Character> chars = new HashSet<Character>();
        for (char c : word.toCharArray()) {
            chars.add(c);
        }
        boolean match = true;
        for (Character c : chars) {
            String s = "" + c;
            if (!dictionaryWord.contains(s)) {
                match = false;
                break;
            }
        }
        if (match == true) 
            System.out.println(dictionaryWord);
    }

在上面的代码中,当然可以将集合创建移出while循环。

更有效的解决方案可能是也从dictionaryWord 创建一个Set,然后检查两个集合的交集是否与表示word 的集合相同。
这将是:

    String word = "dog";
    Set<Character> set1 = new HashSet();
    for (char c : word.toCharArray()) {
        set1.add(c);
    }
    String  dictionaryWord;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    while((dictionaryWord = br.readLine()) != null)  {
        Set<Character> set2 = new HashSet();
        for (char c : dictionaryWord.toCharArray()) {
            set2.add(c);
        }           Set<String> intersection = new HashSet(CollectionUtils.intersection(set1, set2));
        if (set1.equals(intersection)) {
            System.out.println(dictionaryWord);
        } else System.out.println("bad");
    }

使用来自 apache commons 的 CollectionUtils.intersection()

【讨论】:

  • 你能举出这个例子吗?如果可能,谢谢
  • @stackoverflow:刚刚提供了一个从 System.in 读取的代码,并且匹配“dog”,您可以查看一下。
  • @stackoverflow:我还添加了另一种更有效的方法。
  • 你不需要CollectionUtilsset2.retainAll(set1); if(set1.equals(set2))... 也能做到。
  • @MarkoTopolnik:是的,编辑了评论 - 我在第一次阅读时误解了你。 OP 明确要求 26 个字符,所以是关于回答特定问题 - 而不是一般情况......所以对于这个 specific 问题 - int 解决方案尽可能快。
【解决方案2】:
public static boolean containsAllCharacters(String word, Set<String> characters){
    int i = 0;
    int wordLength = word.getLength();
    while (i <= wordLength && characters.contains(word.get(i++)){}
    return i==wordLength;
}

【讨论】:

  • 我不认为这是正确的。当您到达“m”时,输入“教条”和字符集“ogd”会发生什么?
  • 是的,我从@Marko 看到了解决方案,并提供了他的方法的实现。我会修改我的答案。
【解决方案3】:
public static void main(String[] args) {
  final BitSet reqChars = new BitSet(26);
  for (char c : "dog".toCharArray()) reqChars.set(Character.toLowerCase(c) - 'a');
  for (String w : new String[] {"god", "dogma", "megalogdon", "dorm"})
    if (hasAllChars(w, reqChars)) System.out.println(w);
}

public static boolean hasAllChars(String in, BitSet req) {
  req = (BitSet)req.clone();
  for (char c : in.toCharArray()) {
    req.set(Character.toLowerCase(c) - 'a', false);
    if (req.isEmpty()) return true;
  }
  return false;
}

【讨论】:

  • 这是一个糟糕的解决方案,因为您在错过之后会走到单词的末尾。假设你有一个 20 个字符的单词,而第二个单词漏掉了。那是 5% 的效率。
  • @Rob 你误解了我的代码。我的集合包含所需的字符。允许输入的单词包含所需字符集之外的字符,这不是 miss
  • 是的,这个名字有误导性。 hasAllChars 意味着字符串将包含所有字符。我在回答中做了一个版本。
  • @Rob 它读作“在 具有 req的所有字符”,这就是它的作用。
【解决方案4】:

实际上,这个问题最有趣的部分是如何避免查看字典中的每个单词(尽管原始代码类型掩盖了这一点)。一个可能有趣的答案是:

  1. 按出现频率制作 26 个字符的表格。
  2. 查找每个字符,找出出现频率最低的字符。
  3. 然后匹配包含该字符的单词。

当然,这是假设单个匹配比正则表达式便宜。

关于主题here 的精彩维基百科页面。在这种情况下,差异可能不会很大,但在 e 和 x 的情况下,差异会很大。

【讨论】:

    猜你喜欢
    • 2021-12-16
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多