首页 > 其他分享 >字符串匹配

字符串匹配

时间:2023-12-14 18:13:02浏览次数:29  
标签:pat int lps len ++ 字符串 匹配

KMP 算法

Knuth-Morris-Pratt(KMP) 算法用于搜索给定字符串中的模式。

  • 首先,它在模式中找到称为LPS的重复子串,并将LPS信息存储在数组中。
  • 其次,进行字符串匹配。当发生不匹配时,它利用 LPS 数组来决定从哪里开始下一个匹配,以避免多余的旧比较。

如下图

  • 第一次匹配失败后,右移到已匹配部分数组的最大 前缀=后缀=a 的后缀起始,重新进行匹配
  • 第二次匹配失败后,右移到已匹配部分数组的最大 前缀=后缀=aba 的后缀起始,重新进行匹配

lps 数组的定义

lps[i] 是模式 pattern,0 ~ i 的子串,前缀 = 后缀 的最大长度

lps[i] = the longest proper prefix of pat[0..i] which is also a suffix of pat[0..i]. 

  • 如 abaabac,lps[0] = 0 (a),lps[1] = 0 (ab),lps[2] = 1(aba), lps[3] = 1 (abaa), lps[4] = 2 (abaab), lps[5] = 3 (abaaba), lps[6] = 0 (abaabac)

前缀后缀不能是整个 pattern ,最多到倒数第一个

  • 如 AAAA, lps[0] = 0 (A),lps[1] = 1 (AA),lps[2] = 2 (AAA),lps[2] = 3 (AAAA)

计算 lps 数组

java 代码

public static int[] computeLPS(String pat) {
        int len = 0;
        // i 总是在 len 的前面
        int i = 1;
        int[] lps = new int[pat.length()];
        // lps[0]总是为0
        lps[0] = 0;
        while (i < pat.length()) {
            if (pat.charAt(len) == pat.charAt(i)) {
                len++;
                // 匹配上的长度
                lps[i] = len;
                i++;
            }
            else {
                if (len != 0) {
                    // 不相等,下面的往右拉
                    // 从比 0~len(kmpkmd) 少一个字符的子串(kmpkm) 的最大前后缀 开始比较 (len=lps[kmpkm]=2(km))
                    len = lps[len-1];
                }
                else {
                    // 下面的已经到头了,不能往右拉了。只能上面的 i++ 带来新的可能性
                    i++;
                    // i 加了,lps[i] 必有值
                    lps[i] = 0;
                }
            }
        }
        return lps;
    }

模式匹配

public void kmp(String pat, String txt) {
        int i = 0;
        int j = 0;
        int[] lps = computeLPS(pat);
        List<Integer> res = new ArrayList<>();
        /* // 退出循环条件
         * 后面这样肯定是匹配不上了(长度都不够),所以退出循环
         * kmppkmpkmpkmdkmpkmpk
         *                i
         *              kmpkmdkmpkmpk
         *                j
         */
        while (txt.length()-i >= pat.length()-j) {
            if (txt.charAt(i) == pat.charAt(j)) {
                i++;
                j++;
            }
            
            if (j == pat.length()) {
                // 为啥是 i-j
                /*
                 * kmppkmpkmpkmdkmpkmpk
                 *       i-j          i
                 *        kmpkmdkmpkmpk
                 *                    j 
                 */
                res.add(i-j);
                j = lps[j-1];
            }
            else if (i<txt.length() && txt.charAt(i) != pat.charAt(j)) {
                if (j == 0) {
                    i++;
                }
                else {
                    j = lps[j-1];
                }
            }
        }
        System.out.print(res);
    }

示例

 

标签:pat,int,lps,len,++,字符串,匹配
From: https://www.cnblogs.com/suBlog/p/17901714.html

相关文章

  • 对象的数据处理方法,要对对象属性进行数组操作(list数组中每一项与column数组中的valu
       //需要对对象属性进行数组操作时,使用Object.entries()方法    varlist=['V11046_052','V11046_051','V11046_50','V11046_0511'];    varcolumn=[{'观测时间':'D_DATETIME'},{'小时内极大风速出现时间':'V......
  • 查找列表(表格的列名)是否包含某些列名字符串
    lis=["非关键词","关键词1","/s关键词2/s","重复的关键词1"]keywords=["关键词1","关键词2","关键词3"]result={}foriinkeywords:find=Falseforj,kinenumerate(lis):ifnotfind:......
  • navicat链接oracle时报错,检查是否是oci.dll库不匹配的问题
     1:安装Oracle数据库,安装时类型选择共享服务器,不要选专享服务器。2:确定Oracle,Navicat,OracleClient的位数,确保你的oracle数据库的位数与navicat位数一致,即:32v32,64v643:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html,在这个页面下载和......
  • Arcgis中通过函数实现字符串截取
    效果从字符串中提取最右侧的符号,如“/”后面的字符串步骤1、VBdimbbindex=instrrev([WGCJ],"/")bb=right([WGCJ],len([WGCJ])-index)2、pythondefbb(aa):index=(aa.rfind("/"))bb=aa[index+1:]returnbb......
  • 字符串
    字符串反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。示例1:输入:s=["h","e","l","l","o"]输出:["o","l","l","e","h&......
  • 隐藏IAT和字符串
    隐藏IAT和字符串0x01IATIAT即导入表,它记录了我们的文件用了哪些函数。在杀软检测恶意程序时,导入表是一个重要的检测项,比如说我们的程序调用了VirtualAlloc、CreateThread,且VirtualAlloc的最后一个参数是0x40(即PAGE_EXECUTE_READWRITE),那么在杀软看来,我们的程序就是一个高危......
  • 人工智能 | 什么是字符串?
    什么是字符串?字符串是在任何编程语言中都非常重要的一种数据类型。在Python中,字符串是由引号包裹的任意字符组成的不可变序列,用于表示文本类型数据。字符串定义字符串可以通过使用单引号或双引号或三引号来定义,用于表示文本信息,如姓名、消息等。#使用单引号定义字符串:name='A......
  • 通过正则表达式获取字符串中的省市区
    通过正则表达式获取字符串中的省市区//[^省]+省|.+自治区|[^澳门]+澳门|北京|重庆|上海|天津|台湾|[^香港]+香港|[^市]+市)越前面的优先级越高,会取优先级高的第一个匹配到的进行截取//^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+......
  • String字符串
    String字符串String类是定义在java.lang下面的,是定义好的一个类,使用的时候不需要导包。字符串不可变,他们的值在创建后不能被更改。比较:==号:如果是基本数据类型,则比较的是数据值,如果是引用数据类型,比较的是地址值equals:完全一样的结果才是true,否则是falseequalsIgnor......
  • [Vue]el-radio想要传入全部类型时,label绑定空字符串
    记录一下,原本以为不可以这样绑的。这样就可以空查了。 <el-form-itemlabel="类型"prop="type"><el-radiolabel=""v-model='query.type'@change="handleQuery">全部</el-radio><el-radiolabel="1"v-mode......