训练营0930|字符串(重复的子字符串|字符串总结|双指针)

目录

459.重复的子字符串

字符串总结+双指针方法回顾


 459.重复的子字符串

 如果暴力枚举算法,则枚举字符串里面所有出现的子串,并且去判断枚举的字符串里面是否包含这个子串。

如果i是子串位置终止处,i<n/2,并且s[j]=s[j-i]。

注意i和j的边界条件

class Solution {
    /**
     * 暴力法----->s是否是重复字符串
     * i枚举子串,s[j]=s[j-i]
     *
     * @param s
     * @return
     */
    public boolean repeatedSubstringPattern(String s) {
        int len = s.length();
        char[] ch = s.toCharArray();
        for (int i = 1; i <= (len / 2); i++) {//i标记重复子串的末尾位置
            if (len % i == 0) {//不能整除的话,没有意义
                boolean flag = true;
                for (int j = i; j < len; j++) {
                    if (ch[j] != ch[j - i]) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }
}

如果用kmp算法,首先,如果s是重复子串,则s+s里面刨去本身的s,还能再搜索到s

例如:字符串s:ababab   |    字符串ss(s+s):ababab|ababab

很明显可以再找到一个s,又要不包含两者本身那么就掐头去尾。

找重复子串----->双倍掐头去尾------->若能找到则重复

class Solution {
    /**
     * 库函数----->找重复子串
     *
     * @param s
     * @return
     */
    public boolean repeatedSubstringPattern(String s) {
        String ss = s + s;
        ss = ss.substring(1, ss.length() - 1);//不包括endindex
        return ss.contains(s);
    }
}

利用kmp算法去做这个搜索,即在s+s掐头去尾的主串里面搜索s这个子串

class Solution {
    /**
     * 是否为重复子串
     *
     * @param s
     * @return
     */
    public boolean repeatedSubstringPattern(String s) {
        String ss = s + s;
        ss = ss.substring(1, ss.length() - 1);
        return KMP(ss, s);
    }

    /**
     * KMP算法
     *
     * @param mainer
     * @param pattern
     * @return
     */
    public boolean KMP(String mainer, String pattern) {
        int len1 = mainer.length();
        int len2 = pattern.length();
        if (len1 < len2) {
            return false;
        }
        int[] next = getNext(pattern.toCharArray());
        int i = 0, j = 0;
        while (i < len1 && j < len2) {
            if (mainer.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            } else if (next[j] == -1) {
                i++;
            } else {
                j = next[j];
            }
        }
        return j == len2;
    }

    /**
     * 求next数组,第一个是-1,第二个是0,然后递推,cn中间量
     *
     * @return
     */
    public int[] getNext(char[] ch) {
        if (ch.length == 1) {
            return new int[]{-1};
        }
        int[] next = new int[ch.length];
        next[0] = -1;
        next[1] = 0;
        int cn = 0;
        int i = 2;
        while (i < ch.length) {
            if (ch[i - 1] == ch[cn]) {
                next[i++] = ++cn;
            } else if (cn > 0) {
                cn = next[cn];
            } else {
                next[i++] = 0;
            }
        }
        return next;
    }
}

字符串总结+双指针方法回顾

在字符串章节,常见的库函数比如,valueof,substring,fill,contain等要熟练,并且字符串这边整体翻转然后再局部翻转的思想。

并且字符串的大头KMP算法,包括两大部分,next数组,以及具体查找的时候是怎么跳的,一定要掌握清楚。

双指针算法在翻转字符串,还是滑动窗口这边都有一个广泛的应用,以及去找倒数第k个结点(链表),使用快慢指针的操作要熟练。

2022.10.09补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值