力扣-字符串-kmp

文章介绍了如何使用KMP算法来解决字符串查找问题,包括在主串中查找子串以及判断字符串是否由重复子串组成。KMP算法的核心在于构造next数组,用于在不匹配时快速调整子串位置。在第二个解法中,优化了next数组的使用以判断重复子串模式。

解法:

利用kmp求解,详情见kmp大法。

class Solution {
    public int strStr(String haystack, String needle) {
        int next[]=new int[needle.length()+1];
        getNext(next,needle);//数组是引用数据类型,创建next数组
        int i=1,j=1;
        while(i<=haystack.length()&&j<=needle.length()){
            if(j==0||haystack.charAt(i-1)==needle.charAt(j-1)){
                i++;//如果大串和小串是相等的,两个指针继续走
                j++;//j等于0就代表和子串开头都不相等,全都++
            }else{
                j=next[j];//如果不相等子串指针退回到前缀结尾+1的位置
            }
            if(j>needle.length()){
                return i-needle.length()-1;
            }
        }
        return -1;
    }
   
    public static void getNext(int[] next,String str){
        int i=1,j=0;
        next[1]=0;
        while(i<str.length()){
            if(j==0||str.charAt(i-1)==str.charAt(j-1)){//如果j回溯到0到头了就让他加加到1
                i++;
                j++;
                next[i]=j;//如果i字符和j字符相等,将i+1存入j+1
            }else{
                j=next[j];//如果i字符和j字符不相等,将j字符倒退到上一个相等前后缀,再去比较
            }
        }
    }
}

 

解法:

借用了上一题的next数组,由于上一题的next数组是为了方便求解重复字符串的,所以对于这道题来说这样设计next数组其实并非最优解。

想要判断重复的子串,要获取子串的最长前缀剩下的部分,如果剩下的部分是最小单位比如说ab,abc,可以被整体长度整除,那么我们就可以至少知道最后一位剩下的部分是最小单位长度。

 同时我们还要判断最后一位是不是符合条件的字符,我们知道这是一个重复子串组合成的串,最后一位如果和子串的末尾不相同的话,其前后缀最大长度必然是0。

以上两个条件同时满足,我们就认为这个字符串是一个重复字符串。

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        s=" "+s+" ";
        int len=s.length();
        int[] next=new int[len];
        int i=1,j=0;
        next[1]=0;
        while(i<len-1){
            if(j==0||s.charAt(i)==s.charAt(j)){
                i++;
                j++;
                next[i]=j;
            }else{
                j=next[j];
            }
        }
        if((next[len-1]-1>0)&&(len-2)%((len-2)-next[len-1]+1)==0){
            return true;
        }
        return false;
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值