下面是在 JavaScript 中实现几种常见的字符串匹配算法的示例:
1. 简单的字符串匹配(暴力匹配算法):
function bruteForceStringMatch(text, pattern) {
const n = text.length;
const m = pattern.length;
for (let i = 0; i <= n - m; i++) {
let j;
for (j = 0; j < m; j++) {
if (text[i + j] !== pattern[j]) {
break;
}
}
if (j === m) {
return i;
}
}
return -1;
}
const text = "Hello, world!";
const pattern = "world";
console.log(bruteForceStringMatch(text, pattern)); // 输出:7
2. Knuth-Morris-Pratt (KMP) 算法:
function computeLPSArray(pattern) {
const m = pattern.length;
const lps = Array(m).fill(0);
let len = 0;
let i = 1;
while (i < m) {
if (pattern[i] === pattern[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len !== 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
function KMPSearch(text, pattern) {
const n = text.length;
const m = pattern.length;
const lps = computeLPSArray(pattern);
let i = 0;
let j = 0;
while (i < n) {
if (pattern[j] === text[i]) {
i++;
j++;
}
if (j === m) {
return i - j;
} else if (i < n && pattern[j] !== text[i]) {
if (j !== 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return -1;
}
const text = "Hello, world!";
const pattern = "world";
console.log(KMPSearch(text, pattern)); // 输出:7
3. Boyer-Moore 算法:
function buildBadCharTable(pattern) {
const table = {};
for (let i = 0; i < pattern.length; i++) {
table[pattern[i]] = pattern.length - 1 - i;
}
return table;
}
function BMStringMatch(text, pattern) {
const n = text.length;
const m = pattern.length;
const badCharTable = buildBadCharTable(pattern);
let i = m - 1;
while (i < n) {
let j = m - 1;
while (j >= 0 && pattern[j] === text[i]) {
j--;
i--;
}
if (j === -1) {
return i + 1;
}
i += Math.max(badCharTable[text[i]] || m, 1);
}
return -1;
}
const text = "Hello, world!";
const pattern = "world";
console.log(BMStringMatch(text, pattern)); // 输出:7
4. Rabin-Karp 算法:
以下是 JavaScript 中的 Rabin-Karp 算法示例代码:
const prime = 101; // 选取一个质数作为进制
function RabinKarpSearch(text, pattern) {
const n = text.length;
const m = pattern.length;
const patternHash = hash(pattern, m);
let textHash = hash(text, m);
for (let i = 0; i <= n - m; i++) {
if (textHash === patternHash && checkEqual(text, i, pattern, 0, m)) {
return i;
}
if (i < n - m) {
textHash = recalculateHash(text, i, i + m, textHash, m);
}
}
return -1;
}
function hash(str, len) {
let hashValue = 0;
for (let i = 0; i < len; i++) {
hashValue += str.charCodeAt(i) * Math.pow(prime, i);
}
return hashValue;
}
function recalculateHash(str, oldIndex, newIndex, oldHash, len) {
let newHash = oldHash - str.charCodeAt(oldIndex);
newHash = newHash / prime;
newHash += str.charCodeAt(newIndex) * Math.pow(prime, len - 1);
return newHash;
}
function checkEqual(str1, start1, str2, start2, len) {
for (let i = 0; i < len; i++) {
if (str1[start1 + i] !== str2[start2 + i]) {
return false;
}
}
return true;
}
const text = "Hello, world!";
const pattern = "world";
console.log(RabinKarpSearch(text, pattern)); // 输出:7
Rabin-Karp 算法使用了哈希函数来计算模式串和文本串的哈希值,然后在文本串上滑动模式串进行匹配。如果哈希值匹配,则进一步检查模式串和文本串是否完全匹配。这样可以减少字符串比较的次数,提高算法的效率。Rabin-Karp 算法的时间复杂度可以达到 O(n+m),其中 n 是文本长度,m 是模式长度。