第一次面试遇到算法题,不会做也看不懂,上网查了解答之后也是不明不白的,最后一直搁着,想着后面再学习学习之后回来攻克。
通过网上的一些解答,加上个人理解,勉强做出来了,在此记录一下整道题的分析过程。答案对不对不清楚,并没有搜索到标准的正确答案,如有大神发现答案错误以及分析问题错误请指正,感谢!!!
如题:
应用计算机处理日常事务或者是编写程序的时候,经常需要用到带有通配符的字符串匹配。比如:linux命令行下输入,ls *.txt 就是列出当前目录下所有的结尾是.txt的文件。下面一段函数实现了带有$和*两种通配符的字符串的匹配功能。其中:$表示长度大于0的数字串,*表示任意长度的字符串。要求:按照自己对于算法的理解填写该函数的5个空白。请注意:必须是完全匹配才能返回true,比如1.txt, a.txt可以匹配*.txt, 2.tx或者2.txta不能匹配*.txt。函数的参数与返回值的说明请参见函数的注释。
// 功能描述: 表达式是否匹配成功, $表示长度大于 0 的数字串,*表示任意长的字符串
// 输入参数: 字符串 rule 表示规则;
// 字符串 str 表示待匹配的字符串;
// 返回值:true:匹配成功; false: 匹配失败
代码和分析如下:
bool isRegularMatching(string rule, string str)
{
int lRule = rule.Length;
int lStr = str.Length;
int iRule = 0;
int iStr = 0;
//进入while的条件为-----lRule和lStr都不为null,最少都要传入1个字符,才能进入循环
while (iRule < lRule && iStr < lStr)
//iRule < lRule && iStr < lStr避免数组越界
{
switch (rule[iRule]) //空1 switch (_____(1)_____)
//根据题可知,rule是规则,首字符为通配符,因此要得到 rule[0]
//但是,不能写rule[0],因为之后会通过 控制iRule的方法 ,达到break之后进入default
{
case '*':
{
iRule += 1;
if (iRule >= lRule)
{
return true; //只有一个*号,return true
}
else
{
for (int i = iStr; i < lStr; i++)
{
//判断rule的后缀是否和str的后缀相匹配
//写法2:string.Equals(str.Substring(i), rule.Substring(iRule));
//进到case中,iRule += 1; 此时的 iRule为1
//rule的后缀用rule.Substring(iRule)得到
//str的后缀通过for循环遍历,不断重置i,遍历截取的字符串是否和rule的后缀匹配
if (str.Substring(i) == rule.Substring(iRule)) //空2 if (_____(2)_____)
{
return true;
}
}
}
}
break;
case '$':
{
//直接 return false; 代表是什么条件错误直接返回
//应该首字符不为数字
if (str[iStr] < '0' || str[iStr] > '9' ) //空3 if (_____(3)_____)
{
return false;
}
//
while ((iStr < lStr) && (str[iStr] >= '0') && (str[iStr] <= '9'))
{
//iStr < lStr,获取到带匹配字符串的数字串长度 为iStr
iStr += 1;
}
iRule += 1;
break;
}
default:
//进入到default有三种情况
//情况1: case *,但是没有成功匹配后缀,没有return。break出去
//此时: iRule = 1; iStr = 0;
//情况2: case $,中间没有没有return。break 出去
//此时: iRule = 1; iStr = 数字串的长度;
//情况3: 没有进入case,代表rule首字符不是传入通配符
//此时: iRule = 0; iStr = 0;
{
if (rule[iRule] != str[iStr])
{
return false;
// 情况1可知道,剩下的后缀都不匹配。只有return false。(for循环结束了都没有return ture)
// 情况2可知,$ 匹配数字串,iStr截取了当前数字串长度后,str[iStr]就是代表剩下字符的首位。
// 最后同样是匹配 $ 字符后的字符串是否和 str数字串之后的字符串相匹配
// rule[iRule] != str[iStr] 不相等则后面字符串不同,return false
// 情况3:当首字符既不是 * 也不是 $ 的时候,按字符匹配,错误就return false
}
//用于跳出while循环
iRule += 1;
iStr += 1;
break;
}
}
}
// 1、case进入到 $ 中,但是数字串的匹配却没有return true的情况,可能能触发这个条件(就是数字串匹配会有成功的情况)
// 如果str数字串后面的字符串 和 rule中 $ 字符后的字符串不匹配是会return false的。
// 再加上当数字串(iStr)的长度大于等于str的长度的时候,但iRule却小于lRule(lRule的值取决于str中数字串之后的字符串长度),说明rule中包含了Str
// 因此只有当 rule[iRule] == '*'的时候才能完全匹配。才能return true;否则直接 return false;
// 补充:当进入到case * 时,str匹配完了,而rule没有匹配完,也会进入到if中,是否完全匹配同上
// while循环条件 iRule < lRule && iStr < lStr
// 2、进入到default后,最后跳出了while循环。
// 跳出循环条件 iRule >= lRule || iStr >= lStr
// 如果 iRule < lRule && iStr >= lStr 则进入if
// iRule >= lRule && iStr < lStr 则进入else
// iRule >= lRule && iStr >= lStr 则进入else
// 也就是当str匹配完了,而rule还没匹配完,即只有rule[iRule] == '*'才能完全匹配,参考上1
if (iRule < lRule && iStr >= lStr)
{
if (rule[iRule] == '*')
{
return true;
}
}
// iRule >= lRule && iStr < lStr 则进入else
// 这种情况是rule匹配完了,但是str还有字符没有进行匹配,这种情况返回false
// iRule >= lRule && iStr >= lStr 则进入else
// 只有进入到default中,并且str和rule的长度相等,且完全匹配的时候,才会出现这个情况
// 这种情况返回ture
// 综上情况可知,这里即有可能 return true 也有可能 return false,那也就是返回一个bool表达式,通过判断表达式来得到返回值
// 当iStr < lStr时是 false ,当iStr >= lStr时是true
// 则return iStr >= lStr;
else
{
return iStr >= lStr; //return _____(5)_____;
}
return false;
}
有一个不懂的地方,就是当rule规则即有*号的通配符,又有$通配符,有时是不是会匹配不了,是程序不够完善,还是答案有误。望大佬解答。