字符串通配符(Java语言)

字符串通配符

  • 题目
  • 解题
      • 代码

题目

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

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

输出:
返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false
数据范围:字符串长度:1≤s≤100
进阶:时间复杂度:O(n^2)\O(n 2 ) ,空间复杂度:O(n)\O(n)

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

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

示例1
输入:te?t*.*
输入:txt12.xls
输出:false

示例2
输入:z
输入:zz
输出:false

示例3
输入:pq
输入:pppq
输出:false

示例4
输入:**Z
输入:0QZz
输出:true

示例5
输入:?Bc?
输入:abcd
输出:true

示例6
输入:h*?a
输入:h#a
输出:false
说明: 根据题目描述可知能被
和?匹配的字符仅由英文字母和数字0到9组成,所以?不能匹配#,故输出false

示例7
输入:ppqppq*pp***ppq
输入:pppppppqppqqppqppppqqqppqppqpqqqppqpqpppqpppqpqqqpqqp
输出:false

解题

注意:

  1. 不区分大小写。
  2. 其中的通配符,不能匹配出了数字和字符之外的字符。

思路:
使用动态规划。

  1. 构造一个 boolean 类型的二维数组,以 带有通配符的字符串 的长度 +1 为列数, 以 需要匹配的字符串 的长度 + 1 为行数。如下图。
    字符串通配符(Java语言)_第1张图片

  2. 先添加第一行和第一列的值。用行中所存的值和列中所存的值进行比较,行和列分开讨论(第一行的第一个值为 true)。
    第一行 : 1)遇到 ?通配符 填 false,2)遇到 * 通配符 填 前一个空的值,3)遇到字符 false。
    第一列:出了第一个空为 true,其他的空都为 false。

    举例: 就如下图所示,第一行,第一个空为true,第二个空为false(t为字符),第三个空为false(e为字符),第四个空为 false(遇到 ?填false),第五个空为 false(遇到 * 填前一个空为 false),第六个空填 false,第七个空填false。
    字符串通配符(Java语言)_第2张图片

  3. 添加剩余空的值,列中的值和行中的值进行比较。
    1)如果 booleans[i][j] 的行的值和列的值相等,booleans[i][j] == booleans[i-1][j-1]。
    2)如果 booleans[i][j] 行的值或列的值是 ? ,则 booleans[i][j] == booleans[i-1][j-1]。
    3)如果 booleans[i][j] 行的值或列的值是 * ,则 booleans[i][j] == booleans[i][j-1] && booleans[i-1][j]。

    字符串通配符(Java语言)_第3张图片

  4. 如果最后一个值为 true 则这两个字符串能匹配,如果最后一个值为 false 则这两个字符串不能匹配。

代码

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str1 = sc.nextLine().toUpperCase();   //为了不区分大小写,把所有的字符都变成大写
        String str2 = sc.nextLine().toUpperCase();
        int length1 = str1.length();
        int length2 = str2.length();
        boolean[][] booleansArray = new boolean[length2+1][length1+1];
        booleansArray[0][0] = true;  //二维数组的第一个元素为 true
        for(int j=1; j<=length1; j++){  //定义二维数组的第一行
            if(str1.charAt(j-1) == '*'){
                booleansArray[0][j] = booleansArray[0][j-1];
            }else{
                booleansArray[0][j] = false;
            }
        }
        for(int i=1; i<=length2; i++){   //定义二维数组的第一列
            booleansArray[i][0] = false;
        }
        for(int i=1; i<=length2; i++){   //定义剩下的内容
            for(int j=1; j<=length1; j++){
                if(str1.charAt(j-1) == '*'){
                    booleansArray[i][j] = (booleansArray[i-1][j] || booleansArray[i][j-1]);
                }else if(str1.charAt(j-1) == '?'){
                    booleansArray[i][j] = booleansArray[i-1][j-1];
                    if(booleansArray[i][j]){
                        if(!((str2.charAt(i-1)>='0' && str2.charAt(i-1)<='9') ||
                                (str2.charAt(i-1)>='A' && str2.charAt(i-1)<='Z'))){   //如果不是字符或数字,不能替换
                            System.out.println("false");
                            return;
                        }
                    }
                }else{
                    if(str1.charAt(j-1) == str2.charAt(i-1) && booleansArray[i-1][j-1]){
                        booleansArray[i][j] = true;
                    }else {
                        booleansArray[i][j] = false;
                    }
                }
            }
        }
        System.out.println(booleansArray[length2][length1]);  //判断二维数组最后一个元素是否为true
    }
}

你可能感兴趣的:(每日一题,java,算法,数据结构,后端,开发语言)