【程序员面试金典】面试题 16.18. 模式匹配

【程序员面试金典】面试题 16.18. 模式匹配

题目描述

描述:你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。

示例 1:

输入: pattern = "abba", value = "dogcatcatdog"
输出: true

示例 2:

输入: pattern = "abba", value = "dogcatcatfish"
输出: false

示例 3:

输入: pattern = "aaaa", value = "dogcatcatdog"
输出: false

示例 4:

输入: pattern = "abba", value = "dogdogdogdog"
输出: true
解释: "a"="dogdog",b="",反之也符合规则

提示:

1 <= len(pattern) <= 1000
0 <= len(value) <= 1000
你可以假设pattern只包含字母"a"和"b",value仅包含小写字母。

解题思路

思路1:最直观的想法是,回溯。首先统计pattern中a的数量numa和b的数量numb,再使用dfs(pindex,vindex,pattern,value)进行pattern和value的模式匹配。在匹配过程中,使用指针pindex表示pattern当前匹配位置,使用指针vindex表示value当前匹配位置。当pindex对应元素为a时:如果a当前已经被赋值,则判断合法性后再进行下一个位置的匹配;反之如果a当前未被赋值,则以value为基础遍历a的长度[0,value.size()],同时判断合法性以及相应处理后再进行下一个位置的匹配。b同a。

//表示pattern中字符a的数量
int numa=0;
//表示pattern中字符b的数量
int numb=0;
//a和b初始均为空格表示未赋值
string a=" ";
string b=" ";
//flag表示是否匹配
bool flag=false;
//pindex表示当前pattern中的字符序号
//vindex表示当前value中的字符序号
void dfs(int pindex,int vindex,string pattern,string value)
{
  if(flag)
    return;
  //a和b均已赋值且长度不匹配
  if(a!=" "&&b!=" "&&numa*a.size()+numb*b.size()!=value.size())
    return;
  //a已赋值但是b未赋值且长度不匹配
  if(a!=" "&&numb>0&&b==" "&&((value.size()-numa*a.size())%numb!=0))
    return;
  //a未赋值但是b已赋值且长度不匹配
  if(a==" "&&numa>0&&b!=" "&&(value.size()-numb*b.size())%numa!=0)
    return;
  //pattern和value均已到达尾部标记成功处理完成
  if(pindex==pattern.size()&&vindex==value.size())
  {
     flag=true;
     return;
  }
  //pattern和value已经越界
  if(pindex>pattern.size()||vindex>value.size())
    return;
  //开始进入正式的匹配过程
  if(pattern[pindex]=='a')
  {
     //a已经被赋值则直接处理
     if(a!=" ")
     {
      //如果value越界或者value接下来部分与a不同
      if(vindex+a.size()>value.size()||value.substr(vindex,a.size())!=a)
        return;
      //反之继续处理
      else
        dfs(pindex+1,vindex+a.size(),pattern,value);
     }
     //a未被赋值则以value为基础挨个枚举a的长度
     else
     {
        //a的长度范围是0~value.size()
        for(int i=0;i<=value.size();i++)
        {
          if(vindex+i>value.size())
            return;
          //pattern第一个是a则b也未被赋值
          if(pindex==0)
            b=" ";
          a=value.substr(vindex,i);
          dfs(pindex+1,vindex+i,pattern,value);
        }
     }
  }
  //开始进入正式的匹配过程
  if(pattern[pindex]=='b')
  {
     //b已经被赋值则直接处理
     if(b!=" ")
     {
      //如果value越界或者value接下来部分与b不同         	 if(vindex+b.size()>value.size()||value.substr(vindex,b.size())!=b)
        return;
     //反之继续处理
     else
        dfs(pindex+1,vindex+b.size(),pattern,value);
     }
     //b未被赋值则以value为基础挨个枚举b的长度
     else
     {
       //b的长度范围是0~value.size()
       for(int i=0;i<=value.size();i++)
       {
          if(vindex+i>value.size())
            return;
          //pattern第一个是a则b也未被赋值
          if(pindex==0)
            a=" ";
          b=value.substr(vindex,i);
          //a和b不能相同
          if(a==b)
            continue;
          dfs(pindex+1,vindex+i,pattern,value);
        }
      }
    }
}
bool patternMatching(string pattern, string value) 
{
   for(int i=0;i<pattern.size();i++)
   {
      if(pattern[i]=='a')
        numa++;
      if(pattern[i]=='b')
        numb++;
   }
   dfs(0,0,pattern,value);
   return flag;
}

总结:万一pattern中不止a和b又该如何处理呢?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值