回朔法/KMP算法-查找字符串

Posted kuillldan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回朔法/KMP算法-查找字符串相关的知识,希望对你有一定的参考价值。

  1. 回朔法:在字符串查找的时候最容易想到的是暴力查找,也就是回朔法。其思路是将要寻找的串的每个字符取出,然后按顺序在源串中查找,如果找到则返回true,否则源串索引向后移动一位,再重复查找,直到找到返回true,或者源串查找完也没有找到返回false;这种方法简单粗暴,但思路清晰。又因为每次查找失败,源串需要回到起始位置的下一个位置开始查找,所以该算法也称为回朔法。
  2. KMP算法:先对要查找的字符串进行分析,找出其中重复的子字符串。然后将目标串与源串比较,一旦比较失败,则不用回朔,而是根据目标串子串的重复情况,直接调到重复子串的下一个位置。这样减少了大量的回朔,算法复杂度得意大量减小。

下面代码演示了回朔法和KMP算法,并作测试。

package org.lyk.main;

import org.lyk.entities.List;

public class Main
{
    public static void main(String[] args)
    { 
        String _source = "hello how are you";
        String _target = "ello how   yo";
        System.out.println(_source);
        System.out.println(_target);
        
        System.out.println(strContain_BF(_source, _target));
        System.out.println(strContains_KMP(_source, _target));
    }  
    
    public static boolean strContains_KMP(String _source, String _target)
    {
        boolean retVal = false;
        if(null == _source || null == _target || "".equals(_source) || "".equals(_target))
            return false;
        char[] source = _source.toCharArray();
        char[] target = _target.toCharArray();
        int sourceLength = source.length;
        int targetLength = target.length;
        if(targetLength > sourceLength)
            return false;
        else if(targetLength == sourceLength)
        {
            for(int i = 0; i < sourceLength; i++)
            {
                if(source[i] != target[i])
                    return false;
            }
            return true;
        } 
        else
        {
            int[] next = getNext(target);
            int currentSourceIndex = 0;
            int currentTargetIndex = 0;
            while(currentTargetIndex < targetLength)
            {
                int k = 0;
                boolean flag = true;
                for(int i = currentTargetIndex; i<targetLength; i++)
                { 
                    if((currentSourceIndex + k) >= sourceLength)
                    { 
                        return false;
                    }
                    
                    if(target[i] == source[currentSourceIndex+k])
                    {
                        k++;
                        continue;
                    }
                    else
                    {
                        flag = false;
                        if(i == 0)
                        {
                            currentSourceIndex++;
                        }
                        else
                        {
                            currentSourceIndex = currentSourceIndex + k;
                        }
                        currentTargetIndex = next[currentTargetIndex];
                        break;
                    }
                }
                if(flag == true)
                    return true;
            }
            return true;
        } 
    }
    
    
    public static int[] getNext(char[] target)
    {
        int targetLength = target.length;
        int[] next = new int[targetLength];
        
        if(targetLength <= 2)
        {
            for(int i = 0; i< targetLength; i++)
            {
                next[i] = 0;
            }
            return next;
        }
        else
        {
            next[0] = 0;
            next[1] = 0;
            for(int i = 2; i<targetLength; i++)
            {
                int count = 0;
                for(int j = 0; j < i-1;j++)
                {
                    boolean flag = true;
                    for(int k = 0; k <=j; k++)
                    {
                        if(target[k] != target[i-1-j+k])
                            flag = false;
                    }
                    if(flag == true)
                        count = j+1;
                }
                next[i] = count;
            }
            return next;
        }
    }
    
    public static boolean strContain_BF(String _source,String _target)
    {
        boolean retVal = false;
        if(null == _source || null == _target || "".equals(_source) || "".equals(_target))
            return false;
        char[] source = _source.toCharArray();
        char[] target = _target.toCharArray();
        int sourceLength = source.length;
        int targetLength = target.length;
        if(targetLength > sourceLength)
            return false;
        else if(targetLength == sourceLength)
        {
            for(int i = 0; i < sourceLength; i++)
            {
                if(source[i] != target[i])
                    return false;
            }
            return true;
        } 
        else
        {
            for(int i = 0; i <= sourceLength - targetLength;i++)
            {
                boolean flag = true;
                for(int j = 0; j < targetLength; j++)
                {
                    if(target[j] != source[i+j])
                    {
                        flag = false;
                        break;
                    }
                }
                if(flag == true)
                    return true;
            }
            return false;
        }
    }
}

 

以上是关于回朔法/KMP算法-查找字符串的主要内容,如果未能解决你的问题,请参考以下文章

回朔法之应用1

矩阵中的路径

kmp算法的个人理解

布线问题(分支限界法)

字符串查找KMP算法

字符串查找KMP算法(转)