E - 带通配符的字符串匹配 - 动态规划
题干
通配符是一类键盘字符,当我们不知道真正字符或者不想键入完整名字时,常常使用通配符代替一个或多个真正字符。通配符有问号 (?) 和星号 () 等,其中,"?" 可以代替一个字符,而 "" 可以代替零个或多个字符。
你的任务是,给出一个带有通配符的字符串和一个不带通配符的字符串,判断他们是否能够匹配。
例如,1?456 可以匹配 12456、13456、1a456,但是却不能够匹配 23456、1aa456; 2*77?8 可以匹配 24457798、237708、27798。
输入格式
输入有两行,每行为一个不超过
20
个字符的字符串,第一行带通配符,第二行不带通配符。
输出格式
如果两者可以匹配,就输出 “matched”,否则输出"not matched"。
Sample Input
1*456?
11111114567
Sample Output
matched
知识点&算法
字符串匹配总是逐位进行的,可以想到动态规划。
用的dp是留出下标0的写法,即dp数组的下标表示位数,而非原字符串下标
dp[i][j]表示i位子串和j位子串能否匹配
考虑边界条件:
两个子串都为空显然可以匹配dp[0][0] = 1
当通配符串首存在连续的’‘时,’'的部位能匹配空串,即
for(int i = 1 ; s[i-1] == '*' ; ++i) dp[i][0] = 1;
注意dp数组下标表示的是位数,映射到字符串下标要-1
考虑状态转移方程:
考虑当前字符为s[i-1],t[j-1]
字符为’?‘时,可匹配任何字符,状态和前一位匹配相同 dp[i][j] = dp[i-1][j-1]
字符为非通配符时时,可匹配对应字符,状态和前一位匹配和当前字符是否相等有关 dp[i][j] = dp[i-1][j-1] && s[i-1] == t[j-1]
字符为’‘时,可匹配空字符,任意一个字符,任意多个字符中的一个 dp[i][j] = dp[i-1][j-1] || dp[i][j-1] || dp[i-1][j]
尤其是匹配多个字符中一个的情况,即dp[i][j-1]的情况,即拿当前的’'去匹配前一位字符的情况
设串长sl,tl,答案即为dp[sl][tl]
用递归应该是可解的,但细节还有些问题
题解
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s,t;
int dp[25][25],sl,tl;
int main()
{
cin>>s>>t;
sl = s.length(