字符串科技
你说的对,但字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为 s="a1a2···an"(n>=0)。它是编程语言中表示文本的数据类型。在程序设计中,字符串(string)为符号或数值的一个连续序列,如符号串(一串字符)或二进制数字串(一串二进制数字)。
字符串匹配
你说的对,但字符串匹配是计算机科学中最古老、研究最广泛的问题之一。一个字符串是一个定义在有限字母表∑上的字符序列。例如,ATCTAGAGA是字母表∑ = {A,C,G,T}上的一个字符串。字符串匹配问题就是在一个大的字符串T中搜索某个字符串P的所有出现位置。其中,T称为文本,P称为模式,T和P都定义在同一个字母表∑上。
一些定义:
字符串匹配:又称模式匹配(pattern matching)。该问题可以概括为「给定字符串 $ S $ 和 $ T $,在主串 $ S $ 中寻找子串 $ T $」。字符 $ T $ 称为 模式串 (pattern)。
暴力做法:从主串 $ S $ 的每个位置开始与模式串 $ T $ 向后匹配,若匹配不成功,则从主串下一个位置与模式串重新匹配。
时间复杂度:$ O(nm) $
实际上暴力算法在随机数据下表现良好——匹配成功的字符数量越多,匹配的概率越低。
但卡到 $ O(nm) $ 也很容易(
KMP 算法
主要思想:充分利用匹配失败的信息,跳过某些已经判断为匹配失败的位置。
如果字符串 $ s $ 的长度为 $ d $ 的前缀 $(1≤d<|s|)$ 和长度为 $ d $ 的后缀相等,称这个前缀是 $ s $ 的一个 border ,将前缀 $ s[1…i] $ 的最长 border 长度记作 $ next(i) $。
border 的性质:$ s[1…i] $ 的所有 border 长度分别为 $ next(i),next(next(i)),next(next(next(i)))... $。
如果当前已经成功匹配了 $ i $ 个字符,且第 $ i+1 $ 个字符不匹配,那么根据 $ next(i) $ 的定义,主串 $ S $ 中从后往前数 $ next(i) $ 位也一定都与模式串 $ T $ 中 $ 1 \sim next(i) $ 位匹配。
于是将 $ T $ 上匹配指针从 $ i $ 转到 $ next(i) $,再与 $ S $ 的字符匹配。
有点抽象,举个栗子:
S ABABABC
T ABABC算出 $ next(i) $:
next 0 0 1 2 0第一次匹配失败:
S ABAB.ABC
T ABAB.C
next 0 0 1 2 0将 $ T $ 上匹配指针从 $ 4 $ 转到 $ next(4) $,继续匹配:
S ABABABC
T   ABABC
next 0 0 1 2 0匹配成功。
这样做是 $ O(n) $ 的,因为 $ j $ 只能在匹配成功时增加 $ 1 $,最多增加 $ n $ 次,从而最多减少 $ n $ 次,也就是嵌套 $ next(i) $ 最多 $ n $ 次。
于是问题就在于如何快速求出 $ next(i) $。
暴力求显然不现实,考虑线性递推。
已知 $ next(1) \sim next(i) $,考虑如何计算出 $ next(i+1) $:
令 $ j = next(i) + 1 $
如果 $ s[j] $ 与 $ s[i+1] $ 不相等,就让 $ next(j) \to j $,直至 $ s[j] $ 与 $ s[i+1] $ 相等,此时 $ next(i+1) = next(j) + 1 $。
发现计算 $ next(i) $ 的过程实际上就是 $ S $ 与本身匹配。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号