题目来源:http://noi.openjudge.cn/ch0206/6252/
6252:带通配符的字符串匹配
总时间限制: 1000ms 内存限制: 65536kB
描述
通配符是一类键盘字符,当我们不知道真正字符或者不想键入完整名字时,常常使用通配符代替一个或多个真正字符。通配符有问号(?)和星号(*)等,其中,“?”可以代替一个字符,而“*”可以代替零个或多个字符。
你的任务是,给出一个带有通配符的字符串和一个不带通配符的字符串,判断他们是否能够匹配。
例如,1?456 可以匹配 12456、13456、1a456,但是却不能够匹配23456、1aa456;
2*77?8可以匹配 24457798、237708、27798。
输入
输入有两行,每行为一个不超过20个字符的字符串,第一行带通配符,第二行不带通配符
输出
如果两者可以匹配,就输出“matched”,否则输出“not matched”
样例输入
1*456?
11111114567
样例输出
matched
-----------------------------------------------------
解题思路
动态规划: dp[i][j], 代表s1的子串[0,i)与s2的子串[0,j)可以匹配
写递推式时分别考虑s1[i-1]是普通字符、’?’和’*’的情况
s1[i-1]==’*’时要考虑’*’与第一个字符匹配、’*’与第二个以后的字符匹配、’*’与空字符匹配三种情形
坑点:第二行可能为空字符串,空字符串可以与任意多个’*’匹配
-----------------------------------------------------
代码
//6252:带通配符的字符串匹配 //总时间限制: 1000ms 内存限制: 65536kB //描述 //通配符是一类键盘字符,当我们不知道真正字符或者不想键入完整名字时,常常使用通配符代替一个或多个真正字符。通配符有问号(?)和星号(*)等,其中,“?”可以代替一个字符,而“*”可以代替零个或多个字符。 // //你的任务是,给出一个带有通配符的字符串和一个不带通配符的字符串,判断他们是否能够匹配。 // //例如,1?456 可以匹配 12456、13456、1a456,但是却不能够匹配23456、1aa456; //2*77?8可以匹配 24457798、237708、27798。 // //输入 //输入有两行,每行为一个不超过20个字符的字符串,第一行带通配符,第二行不带通配符 //输出 //如果两者可以匹配,就输出“matched”,否则输出“not matched” //样例输入 //1*456? //11111114567 //样例输出 //matched // 动态规划: dp[i][j], 代表s1的子串[0,i)与s2的子串[0,j)可以匹配 #include<iostream> #include<string> using namespace std; bool dp[30][30] = {}; int main() { string s1,s2; cin >> s1 >> s2; int n1 = s1.size(), n2 = s2.size(); dp[0][0] = true; int i=0, j=0; for (i=1; s1.at(i-1)=='*'; i++) // 第二行可能会是空字符串,空字符串可以与任意多的*匹配 { dp[i][0] = true; } for (i=1; i<=n1; i++) { for (j=1; j<=n2; j++) { if (s1.at(i-1)=='*' && (dp[i-1][j-1]||dp[i][j-1]||dp[i-1][j])) // dp[i-1][j-1]对应*匹配到的第一个字符 // dp[i][j-1]对应*匹配到的第二个以后的字符 // dp[i-1][j]对应*匹配到空字符 { dp[i][j] = true; } else if (s1.at(i-1)=='?' && dp[i-1][j-1]) { dp[i][j] = true; } else if (s1.at(i-1)==s2.at(j-1) && dp[i-1][j-1]) { dp[i][j] = true; } } } if (dp[n1][n2]) { cout << "matched"; } else { cout << "not matched"; } return 0; }