题目:
对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1
。
说明
在面试中我是否需要实现KMP算法?
- 不需要,当这种问题出现在面试中时,面试官很可能只是想要测试一下你的基础应用能力。当然你需要先跟面试官确认清楚要怎么实现这个题。
样例
如果 source = "source"
和 target = "target"
,返回 -1
。
如果 source = "abcdabcdefg"
和 target = "bcd"
,返回 1
。
解决这道题的思路有两个,①比较暴力的查找方法,时间复杂度为O(m*n),一个个的遍历循环,这种方法不建议使用,这里就不再给出代码;
②使用KMP算法,这个能把时间复杂 度缩短至O(n),Kmp算法的思路就是给出两个字符串source(资源字符串),target(目标字符串),以target字符串为目标 ,计算出每一个位置的相同最长前缀和最大后缀,把每一个位置的匹配长度,存储在next数组中,然后在source字符串中开始匹配,当匹配到第i个不相同的时候,查看target字符串该位置对应的next[i]数组值,然后用source[i]与target[next[i]]值进行匹配,这就是本道题的思路,下面我们用代码来讲解一下,代码如下:
public class Solution { /* * @param source: source string to be scanned. * @param target: target string containing the sequence of characters to match * @return: a index to the first occurrence of target in source, or -1 if target is not part of source. */ public int strStr(String s, String m) { // write your code here if (s==null||m==null||s.length()<m.length()){ return -1; } char[] ss = s.toCharArray(); char[] ms = m.toCharArray(); int si = 0; int mi = 0; int[] next = getNextArray(ms); while (si<ss.length&&mi<ms.length){ if (ss[si] == ms[mi]){ si++; mi++; }else if (next[mi] == -1){ si++; }else { mi = next[mi]; } } return mi==ms.length?si-mi:-1; } public static int[] getNextArray(char[] s){ if (s.length == 0){ return new int[] {-1}; } int[] next = new int[s.length+1]; next[0] = -1; next[1] = 0; int p = 2; int c = 0; while (p<next.length){ if (s[p-1]==s[c]){ next[p++] = ++c; }else if (c>0){ c = next[c]; }else { next[p++] = 0; } } return next; } }