代码随想录算法训练营第九天| 28. 实现 strStr(), 459.重复的子字符串

28. Find the Index of the First Occurrence in a String

KMP

  • 目的
    • 用来快速查找字符串A(文本串)中是否存在字符串B(模式串),即
  • 为什么快
    • TC M+N线性速度,传统两个循环需要 M*N
  • 结构
    • next数组
      • 整个过程其实有点像DP, 用已知求未知
      • java
         private void getNext(int[] next, String s){
                int j = 0;
                next[0] = 0;//初始化
                for(int i = 1; i< s.length(); i++){
                    while(j > 0 && s.charAt(j) != s.charAt(i)){
                        j = next[j - 1]; // 不相等回退到next[j-1]的位置
                    }
                    if ( s.charAt(j) == s.charAt(i)){
                        j++;  // 相等则j++,(最长字串长度+1)
                    }
                    next[i] = j;  // next[i] 赋值
                }
            }
    • 匹配过程
      • 跟求next数组有点类似
      • java
        
        class Solution {
            public int strStr(String haystack, String needle) {
                int[] next = new int[needle.length()];
                getNext(next, needle);
                
                int j = 0;
                for(int i = 0; i < haystack.length(); i++ ){
                    while( j > 0 && needle.charAt(j) != haystack.charAt(i)){
                        j = next[j - 1]; // 如果匹配不上,回退
                    }
                    if( needle.charAt(j) == haystack.charAt(i)){
                        j++; // 如果匹配上 j++
                    }
                    if ( j == needle.length()){ //此时由于上面的j++, j值刚好等于其index
                        return i - j + 1;     //这里理解成求首项index, i - index  + 1 = len = j ——> index =  i - len(j) + 1;
                    }
                }
                return -1;
                
         
        

459. Repeated Substring Pattern

  • 思路
  • KMP方法
    • 求最小重复子串长度 len = s. length() - next[s.length() - 1];
    • 再看这个子串
      • 是否等于原长度
        • 等于 return false,这个说明next[s.length() - 1] = 0 得从头比,说明没有重复的前后缀(子串), 也就是说这个字符串内压根就没重复的形式
        • 不等于原长
          • 看看 len是否能整除 s.length(),照道理,如果true的话,总长度是重复长度的n倍,能整除
  • java
    class Solution {
        public boolean repeatedSubstringPattern(String s) {
            int[] next = new int[s.length()];
            getNext(next, s);  
            int len = s.length() - next[s.length() - 1]; //求最小重复子串
            if (len == s.length()){
                return false;//这种情况就是没有重复的前后缀
            }
            return s.length() % len == 0 ? true : false; //看看 len是否能整除 s.length(),照道理,如果true的话,总长度是重复长度的n倍,能整除
        }
        
        private void getNext(int[] next, String s){ //next 数组
            int j = 0;
            next[0] = 0;
            for(int i = 1; i < s.length(); i++){
                while( j >0 && s.charAt(j) != s.charAt(i)){
                    j = next[j -1];
                }
                if(s.charAt(i) == s.charAt(j)){
                    j++;
                }
                next[i] = j;
            }
        }
    }
  • 移动匹配
    • s+s
      • 去掉头尾的字符
      • 如果含有s就是true
      • java
        
        
        
        class Solution {
            public boolean repeatedSubstringPattern(String s) {
                String doubleS = s + s;
                String newS = doubleS.substring(1, doubleS.length() - 1);
                return newS.contains(s);
              
         //      下面是用KMP求的contains()
        //         int[] next = new int[s.length()];
        //         getNext(next, s);
                
        //         int j = 0;
        //         for(int i = 0; i < newS.length(); i++){
        //             while(j > 0 && newS.charAt(i) != s.charAt(j)){
        //                 j = next[j - 1];
        //             }
        //             if ( newS.charAt(i) == s.charAt(j)){
        //                 j++;
        //             }
        //             if( j == s.length()){
        //                 return true;
        //             }
        //         }
        //         return false;
            
            }
            private void getNext(int[] next, String s){
                int j = 0;
                for(int i = 1; i < s.length(); i++){
                    while( j > 0 && s.charAt(j) != s.charAt(i)){
                        j = next[j - 1];
                    }
                    if ( s.charAt(j) == s.charAt(i)){
                        j++;
                    }
                    next[i] = j;
                }
            }
        
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值