基本概念
- 子串:串中任意个连续字符组成的子序列称为该串的子串。
- 主串:包含子串的串。
-
字典排序
字符串比较大小通过字典排序,本质上是比较 ascll 码的大小。
串和线性表
串和线性表非常像,区别在于:
线性表关注与单个元素的操作,增删改查
-
BF算法
在主串中找到子串的定位操作叫做模式匹配。朴素解法即对主串做大循环,对每个字符做子串长度的小循环。 ```jsx function findIndex(mStr, sStr) { const mLen = mStr.length;
const sLen = sStr.length;
if(mLen < sLen) {
return -1;
}
for (let i=0; i<(mLen-sLen+1); i++) {
for (let j=0; j<sLen; j++) {if (mStr[i+j] !== sStr[j]) {break;}if(j === sLen - 1) {return i;}}
} return -1;
时间复杂度:最坏情况是 O((n-m+1)*m) 对大循环进行到底<a name="XzU5A"></a>## KMP算法**约定主串 `txt` ,子串 `pat`**KMP 算法的不同之处在于,它会花费空间来记录一些信息,让 BF 算法中无意义的比较少一点。KMP 算法永不回退 txt 的指针 i,不走回头路(不会重复扫描 txt),而是借助 dp 数组中储存的信息把 pat 移到正确的位置继续匹配。根据前缀和后缀共有元素的个数,构成部分匹配表,计算出 pat 指针回溯位数 ,移动位数 = 已匹配的字符数 - 对应的部分匹配值。```jsxvar strStr = function(haystack, needle) {var m = haystack.length, n = needle.length;if(!n) return 0;var next = kmpProcess(needle);for(var i = 0, j = 0; i < m;) {if(haystack[i] == needle[j]) { // 字符匹配,i和j都向前一步i++, j++;}if(j == n) return i - j; // needle完全匹配上,返回匹配位置if(haystack[i] != needle[j]) { // 字符不匹配if(j > 0) {j = next[j-1]; // 重置j} else {i++;}}}return -1;};var kmpProcess = function(needle) {var y = 0;var x = 1;var next = new Array(needle.length).fill(0);while (x < needle.length) {if (needle[x] == needle[y]) {y++;next[x] = y;x++;} else if (y > 0) {y = next[y - 1];} else {next[x] = 0;x++;}}return next;}console.log(strStr('abcabcabya', 'abcaby')); // 3
假设x是遍历needle的索引,y是neddle数组从0开始的索引,也是j将要重置的位置(即存入next数组的值)。因为needle的第一个字符没有前后缀,所以next[0]永远是0,所以x从1开始。计算next的过程如下:
- needle[x] != neddle[y],由于y=0,所以next[x]=0,并且x向前一步,如下图:

2.needle[x] != neddle[y],由于y=0,所以next[x]=0,并且x向前一步,如下图:
- needle[x] == neddle[y],如下图:
此时y要先前进一步,next[x]=前进后的y(此时为1),并且x也向前一步,此时next[x]即next[3]=1如下图:
- needle[x] == neddle[y],如下图:
此时y要先前进一步,next[x]=前进后的y(此时为2),并且x也向前一步,此时next[x]即next[4]=2如下图:

5.needle[x] != neddle[y],由于y != 0,说明之前有匹配上的字符串,此时需要移动y至next[y-1],即y=0,再去比较needle[x] 与 neddle[y],注意,y !=0 或者needle[x] != neddle[y]时,x不能前进,要保持在原地,如下图:
根据needle[x] 与neddle[y]相等和不相等的情况,反复上述步骤,直到needle遍历完为止。此时needle[x] !=neddle[y]且y=0,所以next[x]=0。 这时next数组也被填充完了,如下图。
最后得到next数组为:[0, 0, 0, 1, 2, 0]
