繁体   English   中英

如何在Java中将用户输入的字符与字典文件进行比较?

[英]How to compare character input by user to dictionary file in Java?

我需要阅读用户输入并将其与dictionary.txt.进行比较dictionary.txt. 用户可以输入任意数量的字符,并且程序必须返回可以由这些字符组成的所有英语单词。 这些字母可以以任何顺序使用,并且只能使用一次。 例如:

用户输入 :“ odg”

输出: “狗”,“神” ...以及其他任何东西

经过大量的研究,我提出了以下部分解决方案:

  1. 读取用户输入
  2. 转换为字符数组
  3. 根据数组长度遍历文档
  4. 使用indexOf将数组中的每个字符与每一行进行比较,然后打印不返回-1的单词

如何将用户输入的一组字符与文本文件(字典)中的字符进行比较? 字符不必以任何顺序进行匹配。 (如上面的示例所示)

在这里忍受,我知道这一定是执行此任务的最无效的方法之一! 我们将不胜感激关于如何实现我的原始想法的任何其他想法,同时我也愿意接受任何新的更有效的方法来执行此操作。

以下是我到目前为止提出的内容:

  public static void main(String[] args) throws FileNotFoundException {
    BufferedReader reader1 = new BufferedReader(new FileReader(FILENAME));
    Scanner sc = new Scanner(System.in);
    String line;
    ArrayList<String> match = new ArrayList<>();

    System.out.println("Enter characters to see which english words match: ");
    String userInput = sc.next();

    char arr[]  = userInput.toCharArray();
    int i;

        try {

            while ((line = reader1.readLine()) != null) {

                for (i=0; i < arr.length; i++)
                {
                   if ((line.indexOf(userInput.charAt(i)) != -1) && (line.length() == arr.length)) {
                       match.add(line);
                    }
                    else {
                //        System.out.println("no matches");
                    }
                }

            }
            System.out.println(match);
        }

    catch (IOException e) {

        e.printStackTrace();

    }

**当前结果:**

文字档中的字词:

cab
dog
god
back
dogs
quick

用户输入:“ odg”

程序输出:

[god, god, god, dog, dog, dog]

该程序应返回字典中的所有单词,这些单词可以由用户输入的字符串组成,在这种情况下,我将设法返回两个实例,但是每个实例都显示3次(arr.length)。

首先,有趣的问题。 我实施了我的解决方案和Ole VV的解决方案。 这是基于您的帖子的代码。 我测试了您提供的唯一测试用例,不确定是否是您想要的。 让我知道它是否无法按预期工作。

解决方案一:计算O(nk)

public static void main(String[] args) throws IOException {
    BufferedReader reader1 = new BufferedReader(new FileReader(FILENAME));
    Scanner sc = new Scanner(System.in);

    System.out.println("Enter characters to see which english words match: ");
    String userInput = sc.next();

    Map<Character, Integer> counter = count(userInput);
    String line;
    while ((line = reader1.readLine()) != null) {
        Map<Character, Integer> lineCounter = count(line);
        if(lineCounter.equals(counter)) {
            System.out.println(line);
        }
    }
}

public static Map<Character, Integer> count(String input) {
    Map<Character, Integer> result = new HashMap<Character, Integer>();
    for (char c: input.toCharArray()) {
        result.putIfAbsent(c, 0);
        result.put(c, result.get(c) + 1);
    }

    return result;
}

解决方案二:排序O(nk)

public static void main(String[] args) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(FILENAME));
    Scanner sc = new Scanner(System.in);

    System.out.println("Enter characters to see which english words match: ");
    String userInput = sc.next();
    userInput = sort(userInput);

    String line;
    while ((line = reader.readLine()) != null) {
        String sortedLine = sort(line);
        if(sortedLine.equals(userInput)) {
            System.out.println(new String(line));
        }
    }
}

// counting sort
public static String sort(String input) {
    char c[] = input.toCharArray();
    int length = c.length;
    char output[] = new char[length];

    int count[] = new int[256];
    for (int i = 0; i < length; i++) {
        count[c[i]] = count[c[i]] + 1;
    }

    for (int i = 1; i <= 255; i++) {
        count[i] += count[i - 1];
    }

    for (int i = 0; i < length; i++) {
        output[count[c[i]] - 1] = c[i];
        count[c[i]] = count[c[i]] - 1;
    }

    return new String(output);
}

此类问题的标准解决方案是:对用户输入的字符进行排序。 因此, odg将成为dgoback会变得abck 对于字典中的每个单词,进行相同的排序。 因此cab将变为abcdog将为dgo嘿,这与第一个用户输入相同,因此现在我们知道应该输出该单词了。

此解决方案的优点是您确保每个字母都使用一次。 它甚至会考虑重复的字母:如果相同的字母在用户输入中出现两次,它将仅查找也包含该字母两次的单词。

如果愿意,您可以通过构建地图来预先准备单词列表,其中的键是按字母顺序排序的单词,值是包含这些相同字母的单词的列表。 因此密钥dgo将映射到[dog, god]的列表。 然后,您只需要对输入进行排序并进行查找。

我将向您展示一个易于理解和实施的解决方案,但不是最快的解决方案:

可能的解决方案 :数组排序

将输入字符串和字典单词视为char数组,对其进行排序,然后进行比较:

public static boolean stringsMatchSort(String a, String b) {
    // Different length? Definitely no match!
    if (a.length() != b.length()) {
        return false;
    }

    // Turn both Strings to char arrays
    char[] charsA = a.toCharArray();
    char[] charsB = b.toCharArray();

    // Sort both arrays
    Arrays.sort(charsA);
    Arrays.sort(charsB);

    // Compare them, if equal: match!
    return Arrays.equals(charsA, charsB);
}

请注意我是如何将您的程序/问题的实质变成一种方法的。 然后,您可以在循环访问字典中所有单词的循环中轻松使用该方法。 该方法并不关心单词的来源:文件,集合,其他用户输入,网络等。

通过将程序划分为各个较小的部分,每个部分的责任较小,也有助于简化程序。 这通常称为之,对于处理复杂的问题,无论对于新老程序员,这都是最有价值的策略之一。

其他解决方案 :质数,HashMaps,...

还有其他(包括更快,更优雅)的解决方案。 看一下这些相关的问题,您的问题几乎是以下问题的重复:

补充笔记

根据您的应用程序,最好先将字典读入合适的集合中,这是一个好主意。 如果您对同一个字典执行多个“查询”,这将特别有用。 或者,如果字典真的很大,那么您可以在创建集合的过程中删除重复项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM