day8KMP算法&next数组求解过程

        本体是比较经典的KMP算法的题目,这题可以有两种方法解决:暴力法和KMP

1.暴力法

        定义一个 i 和 j 分别遍历两个字符串,初始化都为0,若不相等 i 就前进一步,直至相等停止前进,此时用while循环遍历接下来的元素是否相等,若遍历完整个字符串则返回对应的下标值。

代码如下:

    public int strStr(String haystack, String needle) {
        for(int left=0;left<haystack.length();left++){
            char ch = haystack.charAt(left);
            if(ch==needle.charAt(0)){
                int right = left;
                int index = 0;
                while(right<haystack.length()&&index<needle.length()){
                    if(haystack.charAt(right)!=needle.charAt(index)){
                        break;
                    }
                    right++;
                    index++;
                }
                if(index==needle.length()){
                    return left;
                }
            }
        }
        return -1;
    }

2.KMP

        在kmp算法中,规定了next数组用来存放前缀表,若遇到不同的字母时,可以直接跳转到对应的位置,并继续进行遍历,省去了从头遍历的时间。

        next数组求解过程(拿别人的哈哈哈):

每次取相同长度的前后缀子串对比是否相同,存在就返回前后缀子串长度,不存在都是0.
a:前后缀都为0,长度为0;
aa:前后缀都为a,长度为1;
aab:前缀aa,后缀ab,不相同,再取前缀a,后缀b,不相同,长度为0;
aaba:前缀aab,后缀aba,不相同,再取前缀aa,后缀ba,不相同,再取前缀a,后缀a,相同,长度为1;
aabaa:前缀aaba,后缀abaa,不相同,再取前缀aab,后缀baa,不相同,再取前缀aa,后缀aa,相同,长度为2;
aabaaf:前缀aabaa,后缀abaaf,不相同,再取前缀aaba,后缀baaf,不相同,再取前缀aab,后缀aaf,不相同,再取前缀aa,后缀af,不相同,再取前缀a,后缀f,不相同,长度为0.

                        

解题步骤:

  • 先定义一个方法,用来获取模式串的前缀表,具体思路看这个视频
  • 获取到前缀表后,遍历两个字符串,在遇到不相同字符串的情况时,利用next数组确定模式串下一个待遍历元素的位置。
  • 若模式串遍历完毕,则返回下标。

代码如下:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值