-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 71 题: 实现一个字符串匹配算法,从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置。 #119
Comments
// 因为 T 的 length 是一定的,所以在循环S的的时候 ,循环当前项 i 后面至少还有 T.length 个元素
const find = (S, T) => {
if (S.length < T.length) return -1;
for (let i = 0; i < S.length - T.length ; i++) {
if (S.substr(i, T.length) === T) return i ;
};
return -1;
}; |
const find = (S,T) => S.indexOf(T) |
|
// 方法一:
const find = (S, T) => S.search(T)
// 方法二:
const find = (S, T) => {
const matched = S.match(T)
return matched ? matched.index : -1
} |
var find = function(S,T){
if(T.length > S.length) return -1;
let index = S.indexOf(T);
let count = [];
while(index != -1){
count.push(index);
index = S.indexOf(T,index + T.length);
}
return count;
} indexOf 可以直接返回字符串所在的位置,但同时是否需要考虑,如果T在S中重复出现的,需要将两个位置都展示出来? |
我的核心思想是使用 let findIndex = (S, T) => {
let index = -1
if (!T.length || T.length > S.length) return index // T 为空字符串或 T 的长度大于 S 均直接返回-1
const arr = S.split(T)
if (arr.length > 1) index = arr[0].length
return index
}
findIndex('FishPlusOrange', 'Plus') // 4
findIndex('FishPlusOrange', 'sulP') // -1
|
function e(s, t){
let reg = new RegExp(t, 'g');
let tArray = [];
let result = [];
while((tArray = reg.exec(s)) !== null){
result.push(tArray.index);
}
return result;
} |
function Test(s, t){ |
用了API的是不是不太体面? getIndexOf = function (s, t) {
let n = s.length;
let m = t.length;
if (!n || !m || n < m) return -1;
for (let i = 0; i < n; i++) {
let j = 0;
let k = i;
if (s[k] === t[j]) {
k++; j++;
while (k < n && j < m) {
if (s[k] !== t[j]) break;
else {
k++; j++;
}
}
if (j === m) return i;
}
}
return -1;
} |
|
你这种方法没有考虑S不存在T的情况,按你这种方法如果不存在的话,返回的是S的长度 |
@LiuMengzhou @Tangjj1996 感谢提醒,已经改正 |
请问下这题主要考什么?为啥indexOf不行? |
循环条件要改成这样吧
|
我觉得是考KMP算法吧 |
var S, T;
var next = [];
// 预计算next数组
function getNext() {
let k = -1,
j = 0;
next[0] = -1;
while (j < len_t) {
if (k == -1 || T[j] == T[k]) {
++j;
++k;
next[j] = k;
} else k = next[k];
}
}
// 返回子串首次出现的位置
function KMP_Index() //T是模式串,S是 主串
{
let i = 0,
j = 0;
getNext();
while (j < len_t && i < len_s) {
if (j == -1 || T[j] == S[i]) {
i++;
j++;
} else j = next[j];
}
if (j == len_t) {
return i - len_t;
} else return -1;
}
//返回子串出现的次数
function KMP_Count() {
let ans = 0;
let i = 0,
j = 0;
getNext();
for (i = 0; i < len_s; i++) {
while (j > 0 && T[j] != S[i]) {
j = next[j];
}
if (T[j] == S[i]) j++;
if (j == len_t) {
ans++;
j = next[j];
}
}
return ans;
}
S = "123454321";
T = "0"
len_s = S.length;
len_t = T.length;
//KMP_Index()如果为-1则没有匹配
console.log(`主串为${S},模式串为${T},模式串首次出现的位置为${KMP_Index()},出现的次数为${KMP_Count()}`); 本质上为KMP算法或者KMP的优化,只要理解next数组的意义和推导,字符串匹配的题目万变不离其宗。 (附上很早之前做的这个算法的PPT链接。。。 |
const find = (S, T) => { |
// 考查indexOf
const includeString = (parent, child) => parent.indexOf(child);
console.log( includeString('hello, my name is dorsey', 'dorsey') ); |
// 应该...没有bug吧^^
function getIndex (S, T) {
const n = S.length;
const m = T.length;
if (n < m) {
return -1;
}
if (n === m) {
return S === T ? 0 : -1;
}
const start = T[0];
const end = T[m - 1];
let i = 0;
while (i < n) {
if (n - i < m) {
return -1;
}
const currS = S[i];
const currSEnd = S[i + m - 1];
let mathing = true;
if (currS !== start || currSEnd !== end) {
i++;
continue;
}
let j = 0;
let step = 0;
while (j < m) {
const currS = S[i + j];
const currSEnd = S[i + j + m - 1];
const isEnd = j === m - 1;
if (mathing) {
const currW = T[j];
mathing = currS === currW;
if (mathing && isEnd) {
return i
}
}
if (!mathing && step !== 0) {
break;
}
if (j > 0 && step === 0) {
if (isEnd) {
step = m;
}
if (currS === start && currSEnd === end) {
step = j;
}
}
j++;
}
i += step || 1;
}
return -1;
} |
|
function findStr(str, f){ |
呃,String.prototype.indexOf的功能不就是干这个的么? |
const strA = "qwertyuiopasfghjkasdflzxcvbnm";
const strB = "asdf";
function findStr(str1, str2) {
const len = str2.length;
const indexArr = [];
str1.split("").forEach((v, i) => {
if (v === str2[0]) indexArr.push(i);
});
let result;
if (!indexArr.length) return "不存在相同的字符串";
indexArr.forEach(idx => {
result = str1.slice(idx, idx + len) === str2 ? idx : null;
});
return result;
}
console.log(findStr(strA, strB)); |
|
最高票的答案写的很好,不过还是不知道为啥不能用indexOf?因为面试题用indexOf太low了么?还是考察点不在这上 |
这个实现的有问题? |
我也想知道这个问题, 难道indexOf 不能实现? |
|
function search(str, str1) {
if (str.includes(str1)) {
return str.indexOf(str1);
} else {
return -1;
}
} |
首先是用了slice的 这个贼简单:
然后我也记得我本科的时候算法课专门有节课讲了pattern matching 回去找了下课件果然是KMP 我结合了阮老师的这个http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 下面是我KMP的写法:
欢迎指正!! |
匹配到最后下标时候,find('123456','456') 为 -1,正确的值应该3; |
// 使用KMP实现 KMP 原理就是 减少text 串的 重复遍历 一次结束 时间复杂度O(m + n)
function KMP(pattern, text) {
let n = pattern.length
let m = text.length
// 计算pattern 的prefix 数组
let arr = new Array(n).fill(0)
let i = 0
let j = 1
while (j < n) {
if (pattern[i] === pattern[j]) {
arr[j] = i + 1
i ++
j ++
} else if (i === 0) {
j ++
} else {
i = arr[i - 1]
}
}
// 进行 比较查找
let h = 0
let k = 0
let count = 0
while (k < n) {
if (text[h] === pattern[k]) {
h ++
k ++
count ++
} else if (k !== 0) {
k = arr[k - 1]
count = 0
} else {
h ++
count = 0
}
}
if (count === n) {
return h - n
}
}
let text = 'acbacbabcbcabcabcbcabca' // 11
let pattern = 'abcabcb'
console.log(KMP(pattern, text)) |
|
function findIdxs(S, T) {
if (S.length < T.length) return []
var reg = new RegExp(T, 'g')
var arr = []
do {
var str = reg.exec(S)
if (str && str.index > 0) {
arr.push(str.index)
}
} while (str && str.index > 0);
return arr
}
var S = 'hkjhkabclkkabcjk'
var T = 'abc'
console.log(findIdxs(S, T)) |
function searchIndex(s,t){ |
我觉得是问题是想问 indexof 的实现算法,不是 api 的运用。 |
// 暴力破解
let text = 'ABABABCABAAABABABABCABAA'
let pattern = 'ABABCABAA'
function findSubString(s, t) {
const n = s.length
const m = t.length
if(m > n) return ''
if(s === t) return s
let index = 0
let i = 0, j = 0
while(i < n) {
while (j < m) {
if(j === m - 1 && s[i] === t[j]) {
console.log(`找到了匹配的位置索引是:${i - j}`)
j = 0
index ++
i = index
}
if(s[i] === t[j]) {
i++
j++
} else {
j = 0
index ++
i = index
}
}
}
}
findSubString(text, pattern)
// KMP算法
let text = 'ABABABCABAAABABABABCABAA'
let pattern = 'ABABCABAA'
function findPrefixTable (pattern) {
let prefixTable = [0]
let m = pattern.length
let preLen = 0
let i = 1
while (i < m) {
if(pattern[i] === pattern[preLen]) {
preLen++
prefixTable[i] = preLen
i++
} else {
if(preLen > 0) {
preLen = prefixTable[preLen - 1]
} else {
prefixTable[i] = preLen
i++
}
}
}
return prefixTable
}
function movePreFixTable(prefixTable) {
const temp = prefixTable
temp.unshift(-1)
temp.pop()
return temp
}
function kmpSearch(text, pattern) {
let n = text.length
let m = pattern.length
let i = 0, j = 0
let prefixTable = movePreFixTable(findPrefixTable(pattern))
while (i < n) {
if(j === m - 1 && text[i] === pattern[j]) {
console.log(`找到了匹配的位置索引是:${i - j}`)
j = prefixTable[j]
}
if(text[i] === pattern[j]) {
i++
j++
} else {
j = prefixTable[j]
if(j === -1) {
i++
j++
}
}
}
}
kmpSearch(text, pattern) |
for循环里的i应该小于S.length-T.length+1吧。您看看,是我理解错了还是您漏写了 |
简单点的: |
|
一行搞定,注意要先判断S是否完整包含T,使用includes即可 ```javascript
function findStr(S, T){
return S.includes(T) ? S.indexOf(T) : -1
} 测试 const S1 = 'abcdefg', T1 = 'cde', T2 = 'fgh'
console.log(findStr(S1, T1)) // 2
console.log(findStr(S1, T2)) // -1
|
调用API的话就search方法
滑动窗口方法:
|
`function isExitF(total, small) {
}` |
|
应用正则应该是最简单的 |
考虑性能的话 kmp 才是正解 |
let str1 = "hellomasd,asdasdasdan";
let str2 = "asdasdasdan";
let fun = (base, target) => {
let conditionLen = base.length - target.length;
for (let i = 0; i <= conditionLen; i++) {
if (base[i] == target[0]) {
let j = 1;
while (j < target.length) {
if (target[j] == base[i + j]) j++;
else break;
}
if (j == target.length) return i;
}
}
return -1;
};
console.log(fun(str1, str2)); |
你用indexOf,面试官会问你有没有其他解法,直到KMP结束😢 |
function foo(target, fragment){ |
您的邮件已收到!O(∩_∩)O!--------Pan
|
const findSubstring = (fullStr, subStr) => {
if (fullStr.length < subStr.length) return -1;
for (let i = 0; i<fullStr.length - 1; i++) {
if (fullStr.slice(i, subStr.length) === subStr) {
return i;
}
}
return -1;
} |
KMP算法? |
您的邮件已收到!O(∩_∩)O!--------Pan
|
|
您的邮件已收到!O(∩_∩)O!--------Pan
|
The text was updated successfully, but these errors were encountered: