【每日一题】day18_01 字符串通配符

学习目标:

目标:熟练运用Java所学知识


学习内容:

本文内容:使用java解决 字符串通配符


文章目录

  • 学习目标:
  • 学习内容:
  • 题目描述
  • 解题思路
  • 实现代码

题目描述

链接:https://www.nowcoder.com/questionTerminal/43072d50a6eb44d2a6c816a283b02036
来源:牛客网

问题描述:

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

输入:

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

输出:

返回匹配的结果,正确输出true,错误输出false

本题含有多组样例输入!

输入描述:

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

输出描述:

返回匹配的结果,正确输出true,错误输出false

示例1

输入
te?t*.*
txt12.xls
输出
false

解题思路

这个题目有两种解法一种是动态规划,一种是深度优先算法

1.动态规划

  • 使用一个二维数组 db 存储当前状态,横坐标表示带有通配符的字符串,纵坐标表示需要匹配的字符串
  • 当前状态分为三种情况:
    ①该位置在带有通配符的字符串对应的字符是* (dp[i][]=’*’)
    ②该位置在带有通配符的字符串对应的字符是? (dp[i][]=’?’)
    ③该位置在带有通配符的字符串对应的字符是正常字母 (dp[i][]是字母)
  • 当dp[i][]是* 时,该位置的状态dp[i][j]取决于dp[i][j-1]或dp[i-1][j],这两个位置有一个是true时dp[i][j]就是true,因为*可以匹配0个、一个或多个。当dp[i][j]的true取决于dp[i-1][j]时,表示匹配0个;取决于dp[i][j-1]表示匹配个一个或多个
  • 当dp[i][]是?时,该位置的状态dp[i][j]取决于dp[i-1][j-1],表示当两个字符串的前一个位置匹配时,当前位置就匹配
  • 当dp[i][]是字母时,该位置的状态dp[i][j]取决于dp[i-1][j-1]与两个字符中的当前位置的字母是否相等,只有前一个位置匹配且当前位置的字母相等,dp[i][j]才是true

初始化

  • 将dp[0][0]初始化为true,因为对应的字符都输空
  • 将第0行其他的都初始化为false
  • 第0列的初始化取决于上一行的第0列和当前行的带有通配符的字符串是不是*
  • 只有当上一行第0列是true且当前位置的带有通配符的字符串对应的字符是*,才是true
    代码表示:
dp[0][0]=true;
for(int i=1;i<matrix.length;i++){
     
               dp[i][0]=dp[i-1][0]&&str1.charAt(i-1)=='*';
           }

图解:
【每日一题】day18_01 字符串通配符_第1张图片

  1. 深度优先搜索:
    深度优先递归时的退出条件是①当两个字符串递归的位置都等于字符串长度返回true②只有其中一个字符串递归的位置等于长度,返回false
    递归时分为四种情况
    1 带通配符字符串递归的位置是*
    2 .带通配符字符串递归的位置是?
    3.两个字符串递归的位置字符相等
    4.两个字符串递归的位置字符不相等

实现代码

  • 动态规划:
import java.util.*;

public class Main{
     
    public static void main(String[] args){
     
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
     
            String str1=sc.next();
            String str2=sc.next();
            //存放每一个位置状态的数组
            boolean[][] dp =new boolean[str1.length()+1][str2.length()+1];
            dp[0][0]=true;//初始化
            //初始化
            for(int i=1;i<dp.length;i++){
     
                dp[i][0]=dp[i-1][0]&&str1.charAt(i-1)=='*';
            }
            for(int i=1;i<dp.length;i++){
     
                for(int j=1;j<dp[0].length;j++){
     
                    if(str1.charAt(i-1)=='*'){
     
                        //当前位置带有通配符的字符串对应的字符是*
                        dp[i][j]=dp[i-1][j]||dp[i][j-1];
                    }else if(str1.charAt(i-1)=='?'){
     
                        //当前位置带有通配符的字符串对应的字符是?
                        dp[i][j]=dp[i-1][j-1];
                    }else{
     
                        //当前位置带有通配符的字符串对应的字符是字母
                        dp[i][j]=dp[i-1][j-1]&&str1.charAt(i-1)==str2.charAt(j-1);
                    }
                }
            }
            System.out.println(dp[str1.length()][str2.length()]);
        }
    }
}
  • 深度优先算法
import java.util.Scanner;

public class Wildcard2 {
     
    public static void main(String[] args){
     
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
     
            String str1=sc.next();
            String str2=sc.next();
            System.out.println(match(str1,str2,0,0));
        }
    }
    public static boolean match(String str1, String str2, int a, int b){
     
        if(a==str1.length()&&b==str2.length()){
     
            //退出条件1
            return true;
        }
        if(a==str1.length()||b==str2.length()){
     
            //退出条件2
            return false;
        }
        if(str1.charAt(a)=='*'){
     
            //带通配符字符串递归的位置是*
            return match(str1,str2,a+1,b)|| match(str1,str2,a+1,b+1)|| match(str1,str2,a,b+1);
        }else if(str1.charAt(a)=='?'){
     
            //带通配符字符串递归的位置是?
            return match(str1,str2,a+1,b+1);
        }else if(str1.charAt(a)==str2.charAt(b)){
     
            //两个字符串递归的位置字符相等
            return match(str1,str2,a+1,b+1);
        }else{
     
            //两个字符串递归的位置字符不相等
            return false;
        }
    }
}

你可能感兴趣的:(每日一题,字符串,算法,java,正则表达式)