In-depth understanding of KMP algorithm (13 string search)

Problem Description:
For a given source string and a target string, you should find the first occurrence of the string target location (starting from 0) in the source string. If not, it returns -1.

Sample 1:
Input: source = "source", target = "target"
Output: -1
Sample explained: if the content source is not included in the target, returns -1

Sample 2:
Input: source = "abcdabcdefg", target = "bcd"
Output: 1
Sample explained: If the source contains the contents of the target, returns the target position of the first occurrence in the source where

Ideas to answer:

A: first thought:
must first method we think of: value source loops through each of which, in turn, and for each value of the target inside the comparison, such as the source from the start 0, 0 than the length targetLength and whether the target value of 0 to a value of one-targetLength, does not correspond to the bit than the first pair of source and target future targetLength length value compared to the end of the cycle has been

Continue down can understand:

For example, the following figure: I am better than for the first one to No. 6 source and whether the target of the first phase 0 to 5 and so on, when I compare to No. 5 and found the target and the target character does not match the I need to be moved back an overall target (in terms relative to the source) of 0 to No. 52 as the image pattern, and then re-compare source bit 2 to 7 and target are equal, see Fig. 2
Ai pple Picture 1
(1)
Ai pple Picture 2
(2)

II: Thinking about jumping

Question: Can you jump directly from Figure 1 Figure 3 it,

Then re-posted Figure 1:
Ai pple Picture 1
Figure (1)
Here Insert Picture Description
Figure (3)
become as shown in Figure 1 3 direct means:
from the original target directly moved to fourth place in the first source of (Source relative terms) in this case the source and target bit 4 of phase 0 and the like, so a direct comparison of source and target bit 5 1,

Recall Figure 1:
When 1 compare to No. 4 5th and target the source of when no match is found,
FIG. 3 is started to compare from No. 1 fifth and target the source of,
directly from Figure 1 Jump to Figure 3 means: source of the index do not change, target of the index change
can be seen from Figure 1 to 3 directly but it omits several department

Three: Thinking jump more than a few

For this part if fully understood skip FIG 1 FIG 2 is completely no problem, it may be substantially like Miao Miao

Let's think about that piece of content in Figure 1. If that is the yellow part of the match but not abdab abdac, more than 1-1 as like diagram
Here Insert Picture Description
drawing more than 1-1

As before it can jump directly to FIG. 1 to FIG. 3, FIG multiple skip to 1-3, and then directly compare a source of a first target Mody and 5, as shown
Here Insert Picture Description
in FIG plurality 1-3

Apparently not, at this time does not match the No. 0 bit 4 of the source and target, and how there may be instances bit fifth comparative target of 1st and source of it?

1 to FIG. 3 and FIG multi plurality 1-3 1-1 When we know we can occur source and target bit 4 bit 3 match, then go through the condition of FIG. 3 only when target 0 and the source can be equal to the fourth, i.e. 0 target and the target is equal to the third

之前说过图1是比较到source的第5位和target的第4位,图3是直接从source的第5位和target的第1位开始比较。
这里我们又知道,图1到图3之所以能直接的条件是:target第4位之前2个长度字符串和target的0-第2位字符串相等。

四:总结记录思维

再再说一下,由图1能直接去图3是因为target的0开始2位长度串==第4位往前2位长度字符串

那么我们是不是可以记录一下target第0位往后x个长度串==第y位往前x个字符串,只有有什么好处呢,当我们和source比较到一定位置的时候,发现不匹配了,我们可以像图1-图3那样不改变source的索引,把target移动到合适的位置,继续比较就行了(即那个思维跳转一下)

我们有一个数组,每个数组的索引记为y,数组的值记为x,next[y]=x;比如说对于图1或图3那个target字符串产生的数组next[4]=1(2个长度,但是索引从0开始,所以是1),当target比较到第4位发现和source的特定位不匹配了,那么target的索引改为1,source索引不变,继续比较

上一段很重要哦,结合图1-图3看看

五:产生next[] 值

我们知道next[] 产生的值是target从0到x个字符==y往前x个字符(不包括当前第y位)

0. For the first bit 0 of the target, the forward bit 0 has no value, it is next [0] = 0; meaning (when the target is represented by the 0th bit and source do not match, the next target to be matched position remains 0, that is, when the source index change)
Here Insert Picture Description
of FIG. 1-Next
1. 1 target for the bit, he forward and characters 0 0 0 next characters equal, the next [1 ] = 0;
[2] = 0 2.next;
3. Here Insert Picture Description
for the bit 3 target, he forward one character and the next one character 0 are equal, the next [3] = 1-1 ; need to explain here, the index is zero-based, (because the record is not equal to 0 and I realize you can achieve their distinction, such as substitutes -1 unequal)
...
end up next to an array [0 , 0,0,0,1,0];

Six: the code assigned on
the Internet and the process is not the same, is carried out according to my understanding, it is no doubt correct in the lintCode test passes, and?

public int[] getNext(String ps) {

    char[] p = ps.toCharArray();
    int[] next = new int[p.length];
    if(next.length > 0) {
         next[0] = 0;
    }
    int i = 1;
    int j = 0;
     while (i < p.length) {
     
      if (p[i] == p[j]) {
        next[i] = j;
        i++;
        j++;
      } else {

          j=0;
          next[i]=j;
          i++;
      }
     }
     return next;
  } 

Also attach the same source, change index target to find the target source code in the position of

public int strStr(String source, String target) {
        // Write your code here‘
        
       char[] t = source.toCharArray();
  
       char[] p = target.toCharArray();
  
       int i = 0; // 主串的位置
 
       int j = 0; // 模式串的位置
 
      int[] next = getNext(target);
  
      while (i < t.length && j < p.length) {
  
      if (t[i] == p[j]) { // 当j为-1时,要移动的是i,当然j也要归0
  
            i++;
 
          j++;
 
        } else {
 
         if(j==0) {
             i++;
         }
         j = next[j]; // j回到指定位置
 
      }
    }
    if (j == p.length) {
 
        return i - j;
  
     } else {
  
       return -1;
  
      }
    }

Seven: Complete Solution

public class Solution {
    
   public int[] getNext(String ps) {

    char[] p = ps.toCharArray();
    int[] next = new int[p.length];

    if(next.length > 0) {
         next[0] = 0;
    }
    
    int i = 1;
    int j = 0;

   while (i < p.length) {
      if (p[i] == p[j]) {

        next[i] = j;
        i++;
        j++;
      } else {
      
          j=0;
          next[i]=j;
          i++;
      }
     }
     return next;
  } 
    /**
     * @param source: 
     * @param target: 
     * @return: return the index
     */
    public int strStr(String source, String target) {
        // Write your code here‘
        
       char[] t = source.toCharArray();
       char[] p = target.toCharArray();
  
       int i = 0; // 主串的位置
       int j = 0; // 模式串的位置
       int[] next = getNext(target);
  
       while (i < t.length && j < p.length) {
 
      if (t[i] == p[j]) { // 当j为-1时,要移动的是i,当然j也要归0
           i++;
          j++;
 
        } else {
 
         if(j==0) {
             i++;
         }
         j = next[j]; // j回到指定位置
      }
    }
    if (j == p.length) {
 
        return i - j;
     } else {
       return -1;
      }
    }
    
}
Published 40 original articles · won praise 10 · views 30000 +

Guess you like

Origin blog.csdn.net/ai_pple/article/details/90764679