Java实现 LeetCode 面试题 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="",反之也符合规则
提示:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pattern-matching-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解:

  1. 当pattern为空的情况,如果value也等于空,返回true,否则false
  2. 当pattern不为空的情况
    2.1 如果value为空,判断pattern是否只有一种元素,如果是true,否则false。
    2.2 如果value不为空,分别得到pattern中a和b的个数
    2.2.1 如果a,b中有一个为0,则判断value能否被a或者b的个数平分,并判断每块的字符是否都相等。
    2.2.2 如果a,b都不为0,那么判断如果只使用一个进行匹配a或者b,令另一个匹配空字符,进行2.2.1相同的判断。
    2.2.3 如果2.2.2不成功,那么我们进行枚举匹配。依据公式a*len_a + (n-a)len_b = m。
    len_a: a匹配的字符的长度
    len_b: b匹配的字符的长度
    a:表示pattern中a的个数
    b:表示pattern中b的个数
    n:pattern的长度
    m:value的长度
    依据公式推出len_a和len_b,然后在value中进行匹配,匹配成功true,不成功false。
package QuestionDays.June;

public class day22patternMatching {
    public static void main(String[] args) {
        //此题主要解法是将待匹配字符根据ab分成几块,主要是确定ab分别对应的字符个数,然后进行匹配
        //ca*a + (n-ca)*b = all
        //需要处理当patt,value为空的情况
        //当pattern为空时,如果value也为空 true
        //当pattern不为空时,如果value为空 ,判断pattern是否只由一个字符组成
        //当pattern不为空,value也不为空时,先处理a,b的个数,如何枚举匹配
        String pattern = "aaaaab";
        String value = "xahnxdxyaahnxdxyaahnxdxyaahnxdxyaauxuhuo";
        System.out.println(patternMatching(pattern, value));

    }
    public static boolean patternMatching(String pattern, String value) {
        //1.pattern为空
        if (pattern.length() == 0) return value.length() == 0;
        //2.pattern不为空时
        //2.1value为空时,判断pattern是否为一个字母组成
        char[] c = pattern.toCharArray();
        int n = pattern.length();
        if (value.length() == 0) {
            int v = 0;
            for (int i = 1; i < n; i++) {
                if (c[i] == c[0]) {
                    v++;
                }
            }
            if (v == n - 1) {
                return true;
            }else return false;
        }
        //2.2当pattern和value都不为空时,办正事
        //(1)统计a,b的个数
        int[] cnt = new int[2];
        for (int i = 0; i < n; i++) {
            cnt[c[i] - 'a']++;
        }
        //(2)判断cnt[0],cnt[1]是否有为0的情况
        if (cnt[0] == 0) return helper(value, cnt[1]);
        if (cnt[1] == 0) return helper(value, cnt[0]);

        //2.2.1假设使得a,b其中之一为空,即次数为0
        if (helper(value, cnt[0])) return true;
        else if (helper(value, cnt[1])) return true;

        //2.2.2 a,b都不为空,枚举a,b匹配的长度,使得a*len_a + b*len_b = len_value
        int m = value.length();
        for (int len_a = 1; len_a * cnt[0] <= m - cnt[1]; len_a++) {
            if ((m - len_a * cnt[0]) % cnt[1] != 0) continue;
            int len_b = (m - len_a * cnt[0]) / cnt[1];
            if (check(pattern, value, len_a, len_b)) return true;
        }
        return false;

    }
    //pattern不为空,value不为空,判断是否可以k次切分value
    public static boolean helper(String value, int k) {
        int m = value.length();
        if(m % k != 0) return false;
        int len = m / k;
        for(int i = len; i < m; i+= len) {
            if(!value.substring(i, i + len).equals(value.substring(0,len))) return false;
        }
        return true;
    }

    public static boolean check(String pattern, String value, int len_a, int len_b) {
        String[] ps = { "", ""};
        boolean correct = true;
        char[] c = pattern.toCharArray();
        for(int i = 0, j = 0; i < pattern.length(); i++) {
            //i,j指针都是恰当长度的
            if(c[i] == 'a') {
                if(ps[0].length() == 0) {
                    ps[0] = value.substring(j, j + len_a);
                } else if(!value.substring(j, j + len_a).equals(ps[0])) {
                    correct = false;
                    break;
                }
                j += len_a;
            }else if(c[i] == 'b') {
                if(ps[1].length() == 0) ps[1] = value.substring(j, j + len_b);
                else if(!value.substring(j, j + len_b).equals(ps[1])) {
                    correct = false;
                    break;
                }
                j += len_b;
            }
        }
        if(correct && !ps[0].equals(ps[1])) return true;
        return false;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值