面试题 16.18. 模式匹配

面试题 16.18. 模式匹配

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

思路

直接计算pattern字符串中a和b的个数,然后解二元一次方程组:
len_a × count_a + len_b × count_b = value.size()即可,直接枚举len_a即可。

  • 枚举时需要注意,count_a不能为0,因而必须保证count_a大于等于count_b。
  • pattern为空时,value必须为空。
  • value为空时,pattern为空或者只出现一个字母a。
  • 当value和pattern都不为空时,枚举len_a来解即可。

代码

class Solution {
public:
    bool patternMatching(string pattern, string value) {
        int count_a = 0, count_b = 0;
        for(const char& ch : pattern) {
            if(ch == 'a') {
                count_a++;
            }
            else {
                count_b++;
            }
        }
		//保证count_a不小于count_b,否则交换
        if(count_a < count_b) {
            swap(count_a, count_b);
            for(char& ch : pattern) {
                ch = (ch == 'a'? 'b' : 'a');
            }
        }
		//value为空时,b为0或者a、b都为0
        if(value.empty()) {
            return count_b == 0;
        }
		//value不空,pattern为空时返回false
        if(pattern.empty()) {
            return false;
        }
		//枚举len_a,保证len_a * count_a <= value.size(),这样len_b不为负数
        for(int len_a = 0; len_a * count_a <= value.size(); len_a++) {
            int rest = value.size() - count_a * len_a;
            //当count_b为0时,剩余字符只能为0,count_b不为0时,保证len_b为整数
            if((rest == 0 && count_b == 0) || (count_b != 0 && rest % count_b == 0)) {
                int len_b = (count_b == 0? 0 : rest / count_b);
                string value_a, value_b;
                int pos = 0;
                bool ans = true;
                //根据len_a和len_b切割字符串
                for(const char& ch : pattern) {
                    //切割len_a
                    if(ch == 'a') {
                        string tmp = value.substr(pos, len_a);
                        if(value_a.empty()) {
                            value_a = move(tmp);
                        }
                        else {
                        	//上次切割和今次切割不一致则失败
                            if(value_a != tmp) {
                                ans = false;
                                break;
                            }
                        }
                        pos += len_a;
                    }
                    //切割len_b
                    else {
                        string tmp = value.substr(pos, len_b);
                        if(value_b.empty()) {
                            value_b = move(tmp);
                        }
                        else {
                            if(value_b != tmp) {
                                ans =  false;
                                break;
                            }
                        }
                        pos += len_b;
                    }
                }
                //value_a和value_b不能为相同字符串
                if(ans && value_a != value_b) {
                    return true;
                }
            }
        }
        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值