[leetcode][c++] 28. strstr()

 这是一道比较简单的问题,就是找出母字符串中是否有与子字符串相匹配的字符串。

要注意的就是几点,题目中要求当needle串为空时,要返回0,没有匹配的则返回 -1.

下面是题目的具体描述,haystack代表长的,needle则代表短的。

暴力解法

暴力思想就是从头进行匹配。 

class Solution {
public:
    int strStr(string haystack, string needle) {
        int m = haystack.size();
        int n = needle.size();
        int i,j;
        if(m < n )
            return -1;
        if(n == 0)
            return 0;
        for(i = 0; i <= m-n ; i++)
        {
            for(j = 0; j < n; j++)
            {
                if(haystack[i+j] != needle[j])
                {
                    break;
                }
            }
            if(j == n)
                return i;
        }
        return -1;
    }
};

KMP解法

kmp 解法是解决字符串匹配的好方法,它的原理内容太多,我这里很难叙述清楚,这里仅仅是简单给出代码,有兴趣可以仔细研究一下:

class Solution {
    public int strStr(String haystack, String needle) {
        return kmp(haystack, needle);
    }

    private int kmp (String s1, String s2) {
        if (s2.length() == 0) {
            return 0;
        }
        if (s1 == null || s2 == null || s1.length() < s2.length()) {
            return -1;
        } 
        int[] next = new int[s2.length()];
        next[0] = -1;
        for (int i = 1, k = -1; i < s2.length();) {
            if (k == -1 || s2.charAt(i - 1) == s2.charAt(k)) {
                k++;
                next[i] = k;
                i++;
            } else {
                k = next[k]; // 这里是容易写错的地方,回溯递归
            }
        }
        for (int num : next) {
            System.out.print(num + " ");
        }
        System.out.println();
        for (int i = 0, j = 0; i < s1.length();) {
            if (s1.charAt(i) != s2.charAt(j)) {
                if (next[j] == -1) {
                    i++;
                    j = 0;
                } else {
                    j = next[j];
                }
            } else {
                if (j == s2.length() - 1) {
                    return (i - s2.length() + 1);
                }
                i++;
                j++;
            }
        }
        return -1;
    }

}

还可以对 kmp 进一步改进得到 next 的改进型 nextval 数组,代码如下,由于内容较多,这里也不过多解释,但是仅仅修改了上面得到 next 数组代码的一小部分内容:

class Solution {
    public int strStr(String haystack, String needle) {
        return kmp(haystack, needle);
    }

    private int kmp (String s1, String s2) {
        if (s2.length() == 0) {
            return 0;
        }
        if (s1 == null || s2 == null || s1.length() < s2.length()) {
            return -1;
        } 
        int[] nextval = new int[s2.length()];
        nextval[0] = -1;
        for (int i = 1, k = -1; i < s2.length();) {
            if (k == -1 || s2.charAt(i - 1) == s2.charAt(k)) {
                k++;
                if (s2.charAt(i) == s2.charAt(k)) {
                    nextval[i] = nextval[k];
                } else {
                    nextval[i] = k;
                }
                i++;
            } else {
                k = nextval[k];
            }
        }
        // for (int num : nextval) {
        //     System.out.print(num + " ");
        // }
        // System.out.println();
        for (int i = 0, j = 0; i < s1.length();) {
            if (s1.charAt(i) != s2.charAt(j)) {
                if (nextval[j] == -1) {
                    i++;
                    j = 0;
                } else {
                    j = nextval[j];
                }
            } else {
                if (j == s2.length() - 1) {
                    return (i - s2.length() + 1);
                }
                i++;
                j++;
            }
        }
        return -1;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值