【问题标题】:Text query matching (tricky)文本查询匹配(棘手)
【发布时间】:2014-02-16 21:55:56
【问题描述】:

我在大学时参加了微软编码挑战,这是被问到的问题:

编写一个程序,将两个字符串作为输入,一个是查询,另一个是可能包含也可能不包含该查询的字符串。您的程序需要查找查询是否包含在正文字符串中。

1) 只有在正文中匹配单词的开头时,查询才应该匹配正文。

2) 也就是说,查询的开头也必须是正文中单词的开头。例如,查询“cat”将匹配字符串“cat”、“cat toy”、“this is a cat”和“catty”。但是,查询“cat”与字符串“location”不匹配。

3) 你的程序应该不区分大小写。

4) 您的程序需要能够匹配其中没有空格的查询,即使正文中确实有空格。例如,字符串“Luke Johnston”将与查询“luke j”和查询“lukej”相匹配。

5) 但是,反过来就不行了。查询“luke j”不应匹配字符串“lukejohnston”。

我能够编写满足前 4 个要求的代码,但我无法找到第 5 个要求的解决方案。任何提示/帮助表示赞赏。这是我的代码版本。

package regex;

import java.util.Scanner;

public class TextQueryMatch {
public static void main(String[] args){
    Scanner in = new Scanner(System.in);
    System.out.print("Enter the Text: ");
    String text = in.nextLine();
    text = text.toLowerCase();
    String[] substexts = text.split("\\s");
    text = "";
    for(int i = 0; i < substexts.length; i++){
        char capLetter = Character.toUpperCase(substexts[i].charAt(0));
        text += capLetter + substexts[i].substring(1, substexts[i].length());
    }
    System.out.println(text);
    System.out.print("Enter the Query: ");
    String query = in.nextLine();
    query = query.toLowerCase();
    String[] subquerys = query.split("\\s");
    query = "";
    for(int i = 0; i < subquerys.length; i++){
        char capLetter = Character.toUpperCase(subquerys[i].charAt(0));
        query += capLetter + subquerys[i].substring(1, subquerys[i].length());
    }
    System.out.println(query);
    System.out.print("Match: ");
    if(text.matches("(.*)"+query.charAt(0)+"(.*)")){
        text=text.toLowerCase();
        query=query.toLowerCase();
        System.out.print(text.matches("(.*)"+query+"(.*)"));
    }else{
        System.out.print("False");
    }
}
}

【问题讨论】:

    标签: java regex string match


    【解决方案1】:

    我认为将查询转换为正则表达式足以满足所有给定条件。

    根据问题,

    根据第 1 点和第 2 点,仅当查询字符串位于文本开头或后接空格时,查询才应匹配文本。所以基本上这个正则表达式就像 -

    (^|\s)(query-string)
    

    第3点需要查询不区分大小写,可以在编译query-regex时处理。

    对于第 4 点和第 5 点,即使查询没有空格,查询也应匹配文本,但如果查询中存在空格,则应在文本中正确匹配。

    因此,我们需要以这样的方式转换我们的正则表达式,在每个字符(或空格)之后,正则表达式可以处理可能存在或不存在的空格。这样,我们假设字符(或空格) 必须匹配,而它后面的空格是有条件的。

    这应该可行 -

     public static boolean find_match(String query, String text){
        String regex = "(?:^|\\s)(" + query.replaceAll(".(?!$)", "$0(?:\\\\s*)") + ")";
        //System.out.println("Regex -> " + regex);
        Pattern re = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);    
        return re.matcher(text).find();
     }
    

    测试这个功能 -

    public static void main(String []args){        
        String query1 = "cat";
        String[] text1 = {
            "Cat",
            "caT toy",
            "This is a CaT",
            "caTty",
            "loCation"
        };
        for(String s : text1){
            System.out.println("Query -> " + query1 + "\nText -> " + s + "\n" + find_match(query1, s) + "\n");
        }
        String query2 = "luke j";
        String query3 = "lukej";
        String[] text2 = {
            "Luke Johnson",
            "lukejohnson",
            "Luke      Johson",
            "This is Luke  Johnson",
            "L ukeJohnson",
            "L uke Johnson"
        };
        for(String s : text2){
            System.out.println("Query -> " + query2 + "\nText -> " + s + "\n" + find_match(query2, s));
            System.out.println("Query -> " + query3 + "\nText -> " + s + "\n" + find_match(query3, s) + "\n");
        }    
     }
    

    输出 ->

    Query -> cat
    Text -> Cat
    true
    
    Query -> cat
    Text -> caT toy
    true
    
    Query -> cat
    Text -> This is a CaT
    true
    
    Query -> cat
    Text -> caTty
    true
    
    Query -> cat
    Text -> loCation
    false
    
    Query -> luke j
    Text -> Luke Johnson
    true
    Query -> lukej
    Text -> Luke Johnson
    true
    
    Query -> luke j
    Text -> lukejohnson
    false
    Query -> lukej
    Text -> lukejohnson
    true
    
    Query -> luke j
    Text -> Luke      Johson
    true
    Query -> lukej
    Text -> Luke      Johson
    true
    
    Query -> luke j
    Text -> This is Luke  Johnson
    true
    Query -> lukej
    Text -> This is Luke  Johnson
    true
    
    Query -> luke j
    Text -> L ukeJohnson
    false
    Query -> lukej
    Text -> L ukeJohnson
    true
    
    Query -> luke j
    Text -> L uke Johnson
    true
    Query -> lukej
    Text -> L uke Johnson
    true
    

    希望这有帮助-

    【讨论】:

    • 它有帮助。您能否详细说明正则表达式语句。对于 query="luke j" 它给出 regex=(?:^|\s)(l(?:\s*)u(?:\s*)k(?:\s*)e(?:\s *) (?:\s*)j)。我是使用正则表达式的新手,我指的是this tutorial,但找不到一些符号。
    • 分组符号 , () 和 (?:) 是捕获组和非捕获组。推荐他们here。对于其余的符号,使用this
    • This 教程非常全面,如果您想从头开始正确地开始正则表达式
    【解决方案2】:

    试试这个方法:

    public static boolean match(String text, String query) {
        text = text.toLowerCase();
        query = query.toLowerCase();
    
        String noSpaces = text.replaceAll(" ", "");
        String[] tWords = text.split(" ");
    
        if (text.startsWith(query) || noSpaces.startsWith(query)) {
            return true;
        }
    
        for (int i = 0; i < tWords.length; i++) {
            if (tWords[i].startsWith(query)) {
                return true;
            }
        }
    
        return false;
    }
    

    【讨论】:

    • 非常好的解决方案,但如果我通过 text="A Luke Johnston" 和 query="luke j" 会失败,因为在 for 循环中,i=2 会失败,因为它会比较约翰斯顿和卢克 j。
    【解决方案3】:

    有多种可能的情况来确定您的QUERY 是否包含在BODY 中。让我们来解释一下您在问题中给出的 CAT 和其他示例正文字符串。

    您的查询将具有以下版本:- cat> : cat 在句子之间的情况 <_cat> :当句子以 cat 结尾或后跟 , 或 时的情况。或任何符号(您可能想使用 ASCII 检查后续字符) : 当句子以猫开头时。 :body是单字句猫,可以用SIZE功能来确认。 _ 被称为空间

    首先,你需要将整个正文和查询字符串转换为小写或大写(或者不是因为没有指定匹配操作是否区分大小写的问题)

    【讨论】:

      猜你喜欢
      • 2016-01-12
      • 2022-01-16
      • 1970-01-01
      • 2013-08-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多