算法查找子字符串

1.查找子字符串问题:

For a given source string and a target string, you should output the first index(from 0) of target string in source string.

If target does not exist in source, just return -1.

算法要求:输入源字符串与目标字符串,输入目标字符串在源字符串中的首字符的下标(下标从0开始计算),

如果没有目标字符串返回-1

解决思路1:双重循环(暴力匹配),第一个循环遍历源字符串,第二个循环遍历目标字符串,时间复杂度O(n^2)

    private SubStringIndex(source:string,target:string):number{
        //特殊情况检测
         if(target.length>source.length||!source||!target){
             return -1;
         }
         //减target.length是因为第一层循环不用走最后的几个字符,因为一定不会匹配的
         let res=-1;
         for(let i=0;i<=source.length-target.length;i++){
             if(source[i]==target[0]){//首字符相同才开始第二层循环
                let temp=true;
                for(let j=0;j<target.length;j++){
                    if(source[i+j]!=target[j]){
                        temp=false;
                        break;
                    }
                }
                if(temp){
                    res=i;
                    return res;//第一个找到就退出
                }
            }
         }
         return res;
     }

解决思路2:KMP算法(K、M、P三个大佬想出来的,所以叫KMP)

如果在第二层循环中出现字符不同时,第一层不是退回首字符,而是到一个合适的地方,不浪费之前的计算,那么上面的算法是不是会更加高效呢?

KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

具体实现是通过getNext获得第一层循环的迭代指针在第二层循环失败后应该到达的位置,即当源串中的某个字符跟目标串中的某个字符匹配失配时,模式串下一步应该跳到哪个位置。

如源字符串中在j 处的字符跟目标串在i 处的字符匹配失配时,下一步用next [j] 处的字符继续跟文本串i 处的字符匹配,相当于模式串向右移动 j - next[j] 位。

    //输入源字符串,返回一个next数组
    private getNext(s:string):number[]{
         let next=[];
         next[0]=-1;
         let i=0;
         let j=-1;
         while(i<s.length-1){
             if(j==-1||s[i]==s[j]){
                 i++;
                 j++;
                 next[i]=j;//记录下一个相同字符的下标
             }else{
                 j=next[j];
             }
         }
         return next;
     }

这里的wile可能很难一下就看懂,关键是j=next[j]不太好理解,其实这个while就是一个for的变种,它遍历了一次源字符串,走的每一个i都会设置next[i],如果这个i位置没有对应可到的next就设置为0,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值