字符串匹配算法一:查找子字符串

【题目】

就是给一个很长的字符串str 还有一个字符集比如{a,b,c} 找出str里包含{a,b,c}的最短子串。要求O(n)。

【例子】

字符集是a,b,c,字符串是abdcaabcx,则最短子串为abc。

【分析】

有题意可知,满足要求的字符串只需要包括字符集中的所有字符,并没有顺序要求

当然最容易想到的是做一个字符匹配的过程,但题目要求查找次数为O(n),在思考了几种解决方法后,觉得下面的方案能够达到要求,虽然需要一些额外的空间。

下面我给出自己的解决方案,难免有遗漏的地方,如果路过的朋友有更好的方法,希望不吝赐教

1. 将字符集 (char_set )里的字符存储于一个 Hash_table 中,key 为字符本身,值为该字符所在位置,初始化为 -1,遍历 str 的时候,每遇见一个字符,就更新Hash_table

2. 设置额外变量用于记录查找成功的子字符串的最小长度,和子字符串的开头,结尾位置

3. 开始遍历 str,执行以下操作:

a) sum; // 用于记录 str 中包含了字符集中的字符个数, 如果 sum 等于字符集大小则执行以下程序,否则继续遍历直到满足条件为止

b) front, end; // front,end 分别存放最小子字符串的首末索引

c) for cur_char in str; // 用于记录遍历 str 时的当前字符

如果 cur_char 在字符集 char_set 中,则 Hash_table[cur_char] = str.index(cur_char) // str.index(cur_char) 将cur_char的索引记录

_f = min(Hash_table); // 找出 Hash_table 的最小值

_e = max(Hash_table); // 找出 Hash_table 的最大值

if ( _e - _f ) < min{

min = (_e - _f);

front = _f;

       end = _e;

   }

d) if sum < size(char_set) // 判断字符串 str 查找是否成功, sum 记录了 str 中包含了几个存在于 char_set 中的字符

    return False;

else:

return str[front, end]; // 返回从 front 到 end 位置的子字符串

时间: 2024-10-09 16:45:00

字符串匹配算法一:查找子字符串的相关文章

KMP查找子字符串算法

举例说明: S:  ababcababa P:  ababa KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字.其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n).  在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀.  对

在父字符串中查找子字符串

在父字符串中查找子字符串(指针控制,也可选择标控制) #pragma once #include<iostream> #include<assert.h> using namespace std; char* StrStr(char* source, char* dest) { assert(source&&dest); if (strlen(source) < strlen(dest)) return NULL; char* newSrc = NULL; c

[C语言】模拟实现库函数strstr,查找子字符串

//模拟实现库函数strstr,查找子字符串 #include <stdio.h> #include <assert.h> char * my_strstr( char *dst, const char * src) { assert(dst); assert(src); int i, j, k; for (i = 0; dst[i] != '\0'; i++) { for (j = i, k = 0; src[k] != '\0'&&dst[j] == src[k

用C#通过正则表达式截取字符串中符合条件的子字符串

仅仅作为简单的记录,不多说直接上代码(仅测试使用): private void Test() { Regex ConnoteA = new Regex("^[a-zA-Z]\\d{8}$"); Regex ConnoteAA = new Regex("^[a-zA-Z]{2}\\d{7,10}$"); Regex ConnoteAAA = new Regex("^[a-zA-Z]{3}\\d{5,9}$"); Regex ConnoteAAAA

[Swift]扩展String类:实现find()查找子字符串在父字符串中的位置

类似于C++中的find()函数:比较等于val的范围中第一个元素的迭代器.如果没有元素匹配,则函数最后返回. 返回值是子字符串在父字符串中的位置(下标记录), 如果没有找到,那么会返回一个特别的标记npos(-1). 返回值可以看成是一个Int型的数. 1 //String扩展 2 extension String { 3 // 截取字符串:从index到结束处 4 // - Parameter index: 开始索引 5 // - Returns: 子字符串 6 func subString

js 判断字符串是否包含某字符串,String对象中查找子字符,indexOf

1 var Cts = "bblText"; 2 3 if(Cts.indexOf("Text") > 0 ) 4 { 5 alert('Cts中包含Text字符串'); 6 } indexOf用法:  返回 String 对象内第一次出现子字符串的字符位置.       strObj.indexOf(subString[, startIndex])       参数    strObj       必选项.String 对象或文字.       subStr

Java如何计数替换字符串中第一次出现的子字符串?

在Java编程中,如何拆分正则表达式和字符串? 以下示例演示如何使用Matcher类的replaceFirst()方法替换字符中指定的子字符串的首次出现. package com.yiibai; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ReplaceFirstOccurrence { public static void main(String args[]) { Pattern p

G - Number Sequence( 查找子字符串 )

Given two sequences of numbers : a11, a22, ...... , aNN, and b11, b22, ...... , bMM (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make aKK = b11, aK+1K+1 = b22, ...... , aK+M?1K+M?1 = bMM. If there are more than o

strstr查找子字符串函数

strstr() 函数搜索一个字符串在另一个字符串中的第一次出现.该函数返回字符串的其余部分(从匹配点).如果未找到所搜索的字符串,则返回 false.该函数是二进制安全的. //数组 #include <stdio.h>   char *my_strstr(const char *str, const char *sub_str) {     for(int i = 0; str[i] != '\0'; i++)     {         int tem = i; //tem保留主串中的起