先来说一下回溯法匹配字符串:

对于主字符串有一个target_index,以target_index(不动)为起点,匹配字符串pattern的长度+target_index为终点,逐个进行比较,当发现不符合时,将target_index加1,进行下一轮比较,也就是说最坏的情况需要遍历target中length(target)-length(pattern)个元素。

这种回溯法没有很有效的利用已经得到的信息:当比较到了target_index+j个元素,发现都一样,但是第target_index+j+1个元素不一样时,我们直接就从target_index+1开始重新比较,没有很好的利用target_index+j已经之前的元素一样的信息了。

KMP算法在一定的程度上用到了该信息。

已经知道(target_index,target_index+j)这中间的元素是一样的了,那么target_index该移动多少距离才是效率更高的呢。

比如说target:{"a","n","n","a","c","d","a","n","a","c","a","d","s","a","n","n","a","n","n","a","c","a","n","n","a"}

pattern:{"a","n","n","a","b","a","n","n","a"}

在target_index=0,j=3,的情况下,target=pattern,当j=4时,开始不匹配了

现在将已经匹配的"a","n","n","a"分为数组A和B,即A={"a","n","n","a"};B={"a","n","n","a"};

B从后面与A开始比较

A:"a","n","n","a"

B:               "a","n","n","a"

有一个字符是一样的,统计这种一样字符的个数,设为count(本例中count为0(有一个元素),如果没有这样的个数,则count为-1)

于是target_index移动target_index+length(A)-count

可以这么移动而不是逐个逐个移动的原因在于:在本例中A自我覆盖的个数count为0,如果在target中找到了pattern,也必然是以count中元素开头的,所以length(A)-count不可能是pattern的开头,所以这些元素可以直接略过去。

public class KMPalgorithm {
    
    
    
    public static void main(String[] args) {
        String []word = {"a","n","n","a","c","a","n","n","a"};
        String []target = {"a","n","n","b","c","d","a","n","a","c","a","d","s","a","n","n","a","n","n","a","c","a","n","n","a"};
        //String []word = {"a","b","a"};
        System.out.print(kmp_find(target,word));
    }
    
    public static int overlayFunction(String[]word){
        int length = word.length;
        for(int i = 1;i<length;i++){
            boolean flag = true;
            String[] newWord = new String[length-i];
            int count = -1;
            for(int j = 0;j<length-i;j++){
                newWord[j] = word[j+i];
                if(word[j+i]!=word[j]){
                    flag = false;
                    break;
                }
                count = j;
            }
            if(flag == true){
                return count;
            }
        }
        return -1;
    }
    
    
    public static int kmp_find(String[]target,String []word){
        int lengthT = target.length;
        int lengthW = word.length;
        for(int i = 0;i<lengthT-lengthW+1;){
            boolean flag = true;
            int j1 = 0;
            for(int j = 0;j<lengthW;j++){
                if(target[i+j]!=word[j]){
                    flag = false;
                    j1 = j;
                    break;
                }
                
            }
            if(!flag&&j1 == 0){
                i = i+1;
            }else if(flag==true){
                return i;
            }else{
                String[]pattern2 = new String[j1];
                for(int k = 0;k<j1;k++){
                    pattern2[k] = word[k];
                }
                i = i+j1-1-overlayFunction(pattern2);
                
            }
            System.out.println("查找的target的index"+i);
        }
        return -1;
    }
}

KMP匹配算法的更多相关文章

  1. 搞定KMP匹配算法

    KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...

  2. 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...

  3. 数据结构——串的朴素模式和KMP匹配算法

    一.朴素模式 假设我们要从主串S="goodgoogle"中找到子串T="google"的位置,步骤如下: i表示主串的当前位置下标,j表示子串的当前位置下标, ...

  4. c语言KMP匹配算法与字符串替换算法

    一.字符串匹配算法 (1)传统匹配算法BF int Index_BF(char* S, char* T){ int i=1,j=1; while(i<=strlen(S) && ...

  5. KMP匹配算法 - Number Sequence

    Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M ...

  6. 一眼看懂KMP匹配算法

    KMP算法——快速从字符串M(母串)中找出与字符串Z(子串)匹配的子串 例1: 0 1 2 3 4 5 M:a b c a b d Z:  a b d BF算法(最一般的算法,也叫“蛮力算法”): 将 ...

  7. 字符串匹配算法 - KMP

    前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...

  8. KMP字符串匹配算法理解(转)

    一.引言 主串(被扫描的串):S='s0s1...sn-1',i 为主串下标指针,指示每回合匹配过程中主串的当前被比较字符: 模式串(需要在主串中寻找的串):P='p0p1...pm-1',j 为模式 ...

  9. 字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

随机推荐

  1. SQLSERVER如何查看索引缺失

    SQLSERVER如何查看索引缺失 当大家发现数据库查询性能很慢的时候,大家都会想到加索引来优化数据库查询性能, 但是面对一个复杂的SQL语句,找到一个优化的索引组合对人脑来讲,真的不是一件很简单的事 ...

  2. sencha touch+phonegap+node.js打包

    这讲我们来讲解下如何使用phonegapa创建项目环境并通过她们将sencha touch打包成app,这里我们只讲解打包android的apk,打包ios的过程有点类似,但是需要在mac环境下,最后 ...

  3. JAVA Socket 编程学习笔记(二)

    在上一篇中,使用了 java Socket+Tcp/IP  协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用 UDP 协议来实现 Socket 的通信. 1. 关于UDP UDP协 ...

  4. Hibernate中evict方法和clear方法说明

    Hibernate中evict方法和clear方法说明 先创建一个对象,然后调用session.save方法,然后调用evict方法把该对象清除出缓存,最后提交事务.结果报错: Exception i ...

  5. c#修改config中的AppSettings属性

    Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); cfa.AppS ...

  6. 类的高级:访问修饰符、封装、静态类成员static、内部类;

    访问修饰符: 公开访问(public):对所有子类,非子类访问: 受保护的(protected):只有同包子类.非子类.不同包子类可访问,不同包非子类不可访问: 私有的(private):只有本类可访 ...

  7. Create a Listlink

    #ifndef List_h__ #define List_h__ #include <stdio.h> struct ListNode { int value; ListNode* pN ...

  8. [转]逻辑斯蒂回归 via python

    # -*- coding:UTF-8 -*-import numpydef loadDataSet(): return dataMat,labelMat def sigmoid(inX): retur ...

  9. LB负载均衡层次结构(摘抄)

    作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环境,用户就可以直接访问到我们的应用了.但对于互联网应用,在你的应用和用户之间还隔着一层低调的或厚或薄的负载均衡层软件,它们不显山 ...

  10. ModalPopup 描述

    原文地址:http://ajax.asp.net/ajaxtoolkit/ModalPopup/ModalPopup.aspx ModalPopup 描述 ModalPopup 能够使页面以设计对话框 ...