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

时间:2017-04-05 19:02:00

标签: java string dictionary char

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

用户输入:“odg”

输出:“狗”,“上帝”......以及其他任何人

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

  1. 阅读用户输入
  2. 转换为字符数组
  3. 根据数组长度遍历文档
  4. 使用indexOf将此数组中的每个字符与每行进行比较,然后打印不返回-1的单词
  5. 如何将用户输入的字符集与文本文件(字典)中找到的字符进行比较?字符不必按任何顺序匹配。(如上面使用的示例所示)

    在这里跟我说,我知道这一定是完成这项任务最无效的方法之一!关于如何实现我的原创想法的任何进一步的想法将不胜感激,而我也愿意接受任何新的和更有效的方法来执行此操作。

    以下是我迄今为止提出的建议:

      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]
    

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

3 个答案:

答案 0 :(得分:3)

首先,有趣的问题。我实施了我的解决方案和Ole V.V的解决方案。以下是基于您帖子的代码。我测试了你提供的唯一测试用例,不确定这是否是你想要的。如果它没有按预期工作,请告诉我。

解决方案一:计算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);
}

答案 1 :(得分:1)

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

这个解决方案的优点是确保每个字母只使用一次。它甚至需要重复的字母:如果在用户输入中同一个字母出现两次,它只会找到同样包含该字母两次的单词。

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

答案 2 :(得分:0)

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

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

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

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

请注意我是如何将程序/问题的内容编入方法的。然后,您可以在循环中轻松使用该方法,该循环遍历字典中的所有单词。该方法并不关心单词来自何处:文件,集合,其他用户输入,网络等。

通过将程序划分为较小的部分,每个部分的责任较小,这也有助于简化程序。这通常被称为 divide&amp;在解决复杂问题时,征服是新老程序员最有价值的策略之一。

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

还有其他(包括更快,更优雅)的解决方案。看看这些相关的问题,你的问题几乎与之相关:

附加说明

根据您的应用程序,首先将字典读入合适的集合可能是个好主意。如果您对同一个字典执行多个“查询”,这将特别有用。或者,如果字典非常庞大,您可以在创建集合期间删除重复字段。