strstr函数_算法刷刷刷Leetcode第28题实现strStr()函数&&动态规划之KMP算法

194600c8a88253a952aa9800c3d130a7.png
【题目】
实现 strStr() 函数。

给定一个haystack字符串和一个needle字符串,在haystack字符串中找出needle字符串出现的第一个位置
(从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

【说明】:

当needle是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当needle是空字符串时我们应当返回0。这与C语言的strstr()以及Java的indexOf()定义相符。

【解法一】(暴力解法)算法时间复杂度O(mn)
//此方法时间复杂的高,执行时间长,但容易想到
//74 / 74 个通过测试用例。执行用时:2470 ms。内存消耗:38 MB。
class Solution {
    public int strStr(String haystack, String needle) {
        int a=haystack.length();
        int b=needle.length();
        //边界条件
        if(haystack==null||a<b)return -1;
        if(needle==null||b==0)return 0;
        for(int i=0;i<a;i++){
             //进入循环条件:在大字符串中发现了,小字符串零号索引位置的元素
            if(haystack.charAt(i)==needle.charAt(0)){
                //记录往右走多长
                int len=0;
                //当大字符还没走到头,同时小字符串没走到头,同时大字符串与小字符串当前位置相同
                while(i+len<a&&len<b&&haystack.charAt(i+len)==needle.charAt(len)){
                    len++;
                }
                //如果len等于小字符串长度,说明匹配成了,返回出现的第一个位置
                if(len==b)return i;
            }
        }
        return -1;
    }
}
【解法二】
//return一个三元运算符表达式结果,利用Java indexOf方法,内置库函数,是算法最优解,执行效率高,
//不过这么写对于刷题和算法训练来讲没有什么意义。74 / 74 个通过测试用例。执行用时:0 ms
//0毫秒的用时秒杀一切手写算法
   public int strStr(String haystack, String needle) {
        return haystack.indexOf(needle) >= 0 ? haystack.indexOf(needle) : -1;
    }

【解法三】 kMP算法:

讲义链接https://web.stanford.edu/class/cs97si/10-string-algorithms.pdf

斯坦福KMP算法讲义

动态规划之 KMP 算法详解

//KMP算法的思路就是找到搜索串每个字符之前可以免匹配的最大长度,比如搜索串 abaabb 匹配到最后一个
//字符不匹配,则前面可免匹配的部分为 ab ,从第三个字符开始继续,减少重复无意义的工作。

class Solution {
    public int strStr(String t, String p) {
        //t是被查找的haystack区域,p是要在heystack区域中查找的needle字符串
        int n=t.length();
        int m=p.length();
        if(m==0) return 0;
        //pi就是斯坦福KMP讲义中的π,它就是求p里面的共同前缀与后缀
        int[] pi=new int[m];
        computrPrefix(p,pi);//求解π Table的函数,讲义第11页
        int k=-1;
        //Pattern Matching Implementation
        for(int i=0;i<n;i++){    //KMP,MATCHER
            while(k>=0 && p.charAt(k+1) != t.charAt(i)){
                k=pi[k];         //next character does not match
            }
            if(p.charAt(k+1) == t.charAt(i)){
                k++;             //next character matches
            }
            if(k==m-1){
                return i-m+1;
            }
        }
        return -1;
    }
    //π Table Implementation
    private void computrPrefix(String p,int[] pi){
       //参见算法导论中Chapter32 String Matching中COMPUTE-PREFIX-FUNCTION
       //求pi数组的伪代码(page1006,英文版)
        pi[0] = -1;
        int k = -1;
        int m = p.length();
        for(int i = 1;i < m ;i++){
            while (k >= 0 && p.charAt(k+1) != p.charAt(i)){
                k = pi[k];
            }
            if(p.charAt(k+1) == p.charAt(i)){
                k++;
            }
            pi[i] = k;
        }
    }
}
//74 / 74 个通过测试用例。状态:通过。执行用时:9 ms    内存消耗:39.4 MB
//对比发现执行时间大约比暴力解法快250倍
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值