leetcode459. 重复的子字符串

1.题目描述:

给定一个非空的字符串s,检查是否可以通过由它的一个子串重复多次构成。

2.暴力枚举:

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int len = s.length();
        for (int i = 0; i < len / 2; i++) {
            int con = len / (i + 1);
            String sub = s.substring(0, i + 1);
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < con; j++) {
                sb.append(sub);
            }
            if (sb.toString().equals(s)) return true;
        }
        return false;
    }
}

3.取巧:(充分性和必要性只看其一,另一个较难证,应用KMP算法也是)

解释如下,从题目可以知道重复字符串至少重复n(n>=2)次才满足,用s+s则至少2n次重复,破环第一个和最后一个,在n>=2的前提下2n-2>=n 恒成立,所以中间至少有一个重复n次的字符串。

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String str = s + s;
        return str.substring(1, str.length() - 1).contains(s);
    }
}

4.应用KMP算法:

数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

前缀表减一:

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int len = s.length();
        int[] next = getNext(s);
        if (next[len - 1] != -1 && len % (len - next[len - 1] - 1) == 0) {
            return true;
        }
        return false;
    }

    public int[] getNext(String s) {
        int[] next = new int[s.length()];
        int j = -1;
        next[0] = j;
        for (int i = 1; i < next.length; i++) {
            while (j > 0 && s.charAt(i) != s.charAt(j + 1)) {
                j = next[j];
            }
            if (s.charAt(i) == s.charAt(j + 1)) j++;
            next[i] = j;
        }
        return next;
    }
}

前缀表不减一:

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int len = s.length();
        int[] next = getNext(s);
        if (next[len - 1] != 0 && len % (len - next[len - 1]) == 0) {
            return true;
        }
        return false;
    }

    public int[] getNext(String s) {
        int[] next = new int[s.length()];
        int j = 0;
        next[0] = j;
        for (int i = 1; i < next.length; i++) {
            while (j > 0 && s.charAt(i) != s.charAt(j)) {
                j = next[j - 1];
            }
            if (s.charAt(i) == s.charAt(j)) j++;
            next[i] = j;
        }
        return next;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值