回朔法/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;
        }
    }
}
时间: 2024-10-12 13:42:13

回朔法/KMP算法-查找字符串的相关文章

kmp算法--求字符串子串--《数据结构》严蔚敏

// exam1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using namespace std; void get_next(int* &next,char* s) { int j=0; int i=1; int len=strlen(s); next=(int*)malloc(len*sizeof(int)); memset(next,0,len*sizeof(int));

回朔法求数独

你一定听说过"数独"游戏. 如[图1.png],玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个同色九宫内的数字均含1-9,不重复. 数独的答案都是唯一的,所以,多个解也称为无解. 本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目.但对会使用计算机编程的你来说,恐怕易如反掌了. 本题的要求就是输入数独题目,程序输出数独的唯一解.我们保证所有已知数据的格式都是合法的,并且题目有唯一的解. 格式要求,输入9行,每行9个数字,0代表未知

KMP算法 (字符串的匹配)

视频参考 对于正常的字符串模式匹配,主串长度为m,子串为n,时间复杂度会到达O(m*n),而如果用KMP算法,复杂度将会减少线型时间O(m+n). 设主串为ptr="ababaaababaa";,要比较的子串为a="aab": KMP算法用到了next数组,然后利用next数组的值来提高匹配速度,我首先讲一下next数组怎么求,之后再讲匹配方式. next数组详解 首先是理解KMP算法的第一个难关是next数组每个值的确定,这个问题困恼我很长时间,尤其是对照着代码一

KMP算法解决字符串出现次数

比如主串为:"1001110110" 子串为:"11" 则出现位置分别为:3 4 7 //KMP算法 2015.6.7 #include<iostream> #include<stdlib.h> using namespace std; int main() { char *s = "1001110110"; char *p = "11"; int ar[20] = { 0 }; //next ar[0

【经典算法】回朔法

回溯是遍历所有搜索空间所有可能组态的方法.这些组态也许代表对象的所有排列或这是构建对象集合的所有可能的方法(子集).其他情况包括列举一个图的所有生成树,两个节点的所有路径或是把节点分类成不同颜色的所有不同的方式. 这些问题有一个共同的难点就是我们必须每次产生一个可能的组态.避免重复或遗漏组态的方法就是我们必须定义一个系统性的产生组态的顺序.我们把组合搜索解作为一个向量a=(a1,a2,...,an),向量元素ai来自有限子集S.这样的向量也许表示一个序列,元素ai是排列的第i个元素.或者,向量表

翻牌回朔法解题

#include <cstdlib> #include <iostream> using namespace std; class card{ private: int a[5][5];//原题 int b[5][5];//解决方案 int c[5][5];//桥 int s[5][5];//结果串 int counts;//解数目 public: card (char x[25]); void Backtrack (int t); bool Constraint(int t);

字符串匹配(BF,BM,Sunday,KMP算法解析)

字符串匹配一直是计算机领域热门的研究问题之一,多种算法层出不穷.字符串匹配算法有着很强的实用价值,应用于信息搜索,拼写检查,生物信息学等多个领域. 今天介绍几种比较有名的算法: 1. BF 2. BM 3. Sunday 4. KMP -,BF算法 BF(Brute Force)算法又称为暴力匹配算法,是普通模式匹配算法. 其算法思想很简单,从主串S的第pos个字符开始,和模式串T的第一个字符进行比较,若相等,则主串和模式串都后移一个字符继续比较:若不相同,则回溯到主串S的第pos+1个字符重新

KMP算法学习

一.什么是KMP算法 Knuth-Morris-Pratt 字符串查找算法(常简称为 “KMP算法”)是在一个“主文本字符串” S 内查找一个“词” W 的出现,,以此避免对以前匹配过的字符重新检查.(在原串中匹配模式串) 二.KMP演示 http://staff.ustc.edu.cn/~ypb/jpkc/flash/Find_KMP.swf 三.KMP原理 KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 在KMP算法中有个数组,叫做前缀

【原创】通俗易懂的讲解KMP算法及代码实现

一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想后的优化. 所以本文重点是讲解KMP算法的核心,文章最后会有涉及一些改良过程. 二.KMP算法简介 KMP算法是字符串匹配算法的一种.它以三个发明者命名,Knuth-Morris-Pratt,起头的那个K就是著名科学家Donald Knuth. 三.KMP算法行走过程 首先我们先定义两个字符串作为示