第 71 题: 实现一个字符串匹配算法,从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置
const find = (S, T) => { if (S.length < T.length) return -1 for (let i = 0; i < S.length; i++) { if (S.slice(i, i + T.length) === T) return i } return -1 }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(40)
呃,String.prototype.indexOf的功能不就是干这个的么?
这里S.length - T.length有点小错误,应该改为S.length
最高票的答案写的很好,不过还是不知道为啥不能用indexOf?因为面试题用indexOf太low了么?还是考察点不在这上
这个实现的有问题?
我也想知道这个问题, 难道indexOf 不能实现?
这里题目考的是算法实现,不是api运用
/* KMP的优化算法 (寻找匹配字符串的前缀与后缀最大公共长度,该值仅仅与匹配字符串相关)*/
There will be bugs if S===T
这样是不是更简单一些呀
这题考的是 KMP 算法:
名词
概念
相比于傻瓜式的字符串匹配,即在遍历主子串时,一旦出现对应位置的字符不匹配,主子串都要回溯后再重新遍历匹配。
其实已匹配过的字符,再去回溯匹配是多余,因为前面的字符已经一一匹配对应了,你再右移后就错位了,肯定不会匹配。
KMP 算法就是为了避免主串回溯,子串右移已匹配的最大位数,来避免明知道不会匹配的无效移位。
原理
@jjeejj
S.length - T.length
无法获取 T处于 S 最后处这种情况,应该改为S.length - T.length + 1
首先是用了slice的 这个贼简单:
然后我也记得我本科的时候算法课专门有节课讲了pattern matching 回去找了下课件果然是KMP 我结合了阮老师的这个http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 下面是我KMP的写法:
结果在这里哈:

欢迎指正!!
@jjeejj
匹配到最后下标时候,find('123456','456') 为 -1,正确的值应该3;
for (let i = 0; i < S.length - T.length ; i++) 中的i < S.length - T.length 少了
我的核心思想是使用
split
,假设未匹配到返回-1
:function Test(s, t){
if(s.length < t.length){
return -1;
}else{
return s.indexOf(t);
}
}
用了API的是不是不太体面?
@FishPlusOrange

你这种方法没有考虑S不存在T的情况,按你这种方法如果不存在的话,返回的是S的长度
@LiuMengzhou @Tangjj1996 感谢提醒,已经改正
请问下这题主要考什么?为啥indexOf不行?
循环条件要改成这样吧
我觉得是考KMP算法吧
本质上为KMP算法或者KMP的优化,只要理解next数组的意义和推导,字符串匹配的题目万变不离其宗。
(附上很早之前做的这个算法的PPT链接。。。
http://note.youdao.com/noteshare?id=91749237e787b4aa0b246336ea0c1137 )
const find = (S, T) => {
const indexList = [];
if(S.length < T.length) return -1;
for(let i = 0; i <= S.length - T.length; i++) {
if(S.slice(i, i + T.length) === T) indexList.push(i)
}
return indexList.length? indexList : -1;
}
搜索了一下KMP算法:
https://zh.wikipedia.org/wiki/%E5%85%8B%E5%8A%AA%E6%96%AF-%E8%8E%AB%E9%87%8C%E6%96%AF-%E6%99%AE%E6%8B%89%E7%89%B9%E7%AE%97%E6%B3%95
function findStr(str, f){
var reg = new RegExp(f, 'g');
return reg.exec(str).index;
};
indexOf 可以直接返回字符串所在的位置,但同时是否需要考虑,如果T在S中重复出现的,需要将两个位置都展示出来?