• 牛客出bug(华为机试HJ71)


    Hj71:字符串通配符

    描述

    问题描述:在计算机中,通配符一种特殊语法,广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。
    要求:
    实现如下2个通配符:
    *:匹配0个或以上的字符(注:能被*和?匹配的字符仅由英文字母和数字0到9组成,下同)
    ?:匹配1个字符

    注意:匹配时不区分大小写。

    输入:
    通配符表达式
    一组字符串。

    输出:

    返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false

    数据范围:字符串长度 1≤s≤100 

    进阶:时间复杂度:O(n2) ,空间复杂度 O(n) 

    输入描述:

    先输入一个带有通配符的字符串,再输入一个需要匹配的字符串

    输出描述:

    返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false

    上述为题目,都提示时间复杂度为 O(n2) 了,基本都能想到动态规划吧,废话不多说,先上代码

    1. public static void main(String[] args) {
    2. Scanner in = new Scanner(System.in);
    3. String match = in.nextLine();
    4. String target = in.nextLine();
    5. System.out.println(dp(match, target) ? "true" : "false");
    6. }
    7. /**
    8. * pass:32/34
    9. * eg:
    10. * a*?*c
    11. * a@c
    12. * 预计:false!!!!!!!!!!!!!!!todo sotmw???????
    13. * 实际:true
    14. * @param match
    15. * @param target
    16. * @return
    17. */
    18. public static boolean dp(String match, String target) {
    19. int m = match.length();
    20. int n = target.length();
    21. boolean[][] dp = new boolean[m][n];
    22. // 初始化dp
    23. for (int j = 0; j < n; ++j) {
    24. char c = match.charAt(0);
    25. if (c == '*') {
    26. dp[0][j] = true;//通配符匹配多个
    27. if (m > 1) {
    28. dp[1][j] = match.charAt(1) == target.charAt(j);//第一位的 * 可能不匹配,多初始化一行
    29. }
    30. }
    31. if (j == 0 && (c == '?' || c == target.charAt(0))) {//dp[0][0] 必须初始化
    32. dp[0][j] = true;
    33. }
    34. }
    35. // 常规dp
    36. for (int i = 0; i < m - 1; ++i) {
    37. for (int j = 0; j < n - 1; ++j) {
    38. if (dp[i][j]) {
    39. char mat = match.charAt(i + 1);
    40. if (mat == '*') {
    41. for (int j0 = j; j0 < n; ++j0) {
    42. dp[i + 1][j0] = true;
    43. }
    44. } else if (mat == '?') {
    45. dp[i + 1][j + 1] = true;
    46. } else {
    47. dp[i + 1][j + 1] = mat == target.charAt(j + 1);
    48. }
    49. }
    50. }
    51. }
    52. return dp[m - 1][n - 1];
    53. }

    这个用例用眼睛都能匹配,它告诉我说不行!!!!!!!!就问有没有被坑的感觉!!!!!?

    ===============================分割线===========================

    后来我看到了

    *:匹配0个或以上的字符(注:能被*和?匹配的字符仅由英文字母和数字0到9组成,下同)

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    人为埋雷!!!!!被坑的感觉更强烈了!!!!!!!

    搞些杂七杂八的消耗别人的时间精力,完全违背了练习算法的初衷,伤心了

    ===============================分割线===============================

    都写到这个份上了,附上一份完整通过的代码:

    1. public static void main(String[] args) {
    2. Scanner in = new Scanner(System.in);
    3. String match = in.nextLine();
    4. String target = in.nextLine();
    5. System.out.println(dp(match, target) ? "true" : "false");
    6. }
    7. /**
    8. * pass:32/34
    9. * eg:
    10. * a*?*c
    11. * a@c
    12. * 预计:false!!!!!!!!!!!!!!!todo sotmw???????
    13. * 实际:true
    14. *
    15. * @param match
    16. * @param target
    17. * @return
    18. */
    19. public static boolean dp(String match, String target) {
    20. int m = match.length();
    21. int n = target.length();
    22. boolean[][] dp = new boolean[m][n];
    23. for (int j = 0; j < n; ++j) {
    24. char c = match.charAt(0);
    25. if (c == '*') {
    26. dp[0][j] = true;//通配符匹配多个
    27. if (m > 1) {
    28. dp[1][j] = match(match.charAt(1), target.charAt(j));//第一位的 * 可能不匹配,多初始化一行
    29. }
    30. }
    31. if (j == 0 && match(c, target.charAt(j))) {//dp[0][0] 必须初始化
    32. dp[0][j] = true;
    33. }
    34. }
    35. // 常规dp
    36. for (int i = 0; i < m - 1; ++i) {
    37. for (int j = 0; j < n - 1; ++j) {
    38. if (dp[i][j]) {
    39. char mat = match.charAt(i + 1);
    40. if (mat == '*') {
    41. for (int j0 = j; j0 < n; ++j0) {
    42. dp[i + 1][j0] = checkChar(target.charAt(j0));
    43. }
    44. } else if (mat == '?') {
    45. dp[i + 1][j + 1] = checkChar(target.charAt(j + 1));
    46. } else {
    47. dp[i + 1][j + 1] = match(mat, target.charAt(j + 1));
    48. }
    49. }
    50. }
    51. }
    52. return dp[m - 1][n - 1];
    53. }
    54. /**
    55. * (注:能被*和?匹配的字符仅由英文字母和数字0到9组成,下同)
    56. *
    57. * @param c
    58. * @return
    59. */
    60. public static boolean checkChar(char c) {
    61. return 48 <= c && c <= 57 || 65 <= c && c <= 90 || 97 <= c && c <= 122;
    62. }
    63. /**
    64. * 注意:匹配时不区分大小写。
    65. * 一个注意就要重新抽一个方法封装
    66. *
    67. * @param c1
    68. * @param c2
    69. * @return
    70. */
    71. public static boolean match(char c1, char c2) {
    72. if (c1 == '*') {
    73. return checkChar(c2);
    74. }
    75. if (c1 == '?') {
    76. return checkChar(c2);
    77. }
    78. int m = c1 - c2;
    79. if (m != 0) {
    80. int c11 = c1, c22 = c2;
    81. if (65 <= c1 && c1 <= 90) {
    82. c11 = c1 - 64;
    83. }
    84. if (97 <= c1 && c1 <= 122) {
    85. c11 = c1 - 96;
    86. }
    87. if (65 <= c2 && c2 <= 90) {
    88. c22 = c2 - 64;
    89. }
    90. if (97 <= c2 && c2 <= 122) {
    91. c22 = c2 - 96;
    92. }
    93. m = c11 - c22;
    94. }
    95. return m == 0;
    96. }

    审题远比搬砖重要,下次做华为的题,首先做个 toKengList.

  • 相关阅读:
    短视频拍摄要注意啥细节?从服化道到拍摄思路,注意细节方能成功
    Spring学习_day10
    1.6 - CPU组成
    H3C opsf/rip/ftp/telent/nat/acl综合
    JDK8-Predicate接口使用举例
    数据结构五分钟精通 之 正则表达式(Python)
    自托管图像共享服务Slink
    OpenCV图像处理——目标追踪
    ASP.NET之ViewState学习与联想
    Linux基础指令(一)
  • 原文地址:https://blog.csdn.net/weixin_41346635/article/details/134252470