459. 重复的子字符串

459. 重复的子字符串

原题链接:

459. 重复的子字符串

https://leetcode.cn/problems/repeated-substring-pattern/submissions/

完成情况:

解题思路:

java 复制代码
思路与算法

如果一个长度为 nnn 的字符串 sss 可以由它的一个长度为 n′n'n 
′
  的子串 s′s's 
′
  重复多次构成,那么:

nnn 一定是 n′n'n 
′
  的倍数;

s′s's 
′
  一定是 sss 的前缀;

对于任意的 i∈[n′,n)i \in [n', n)i∈[n 
′
 ,n),有 s[i]=s[i−n′]s[i] = s[i-n']s[i]=s[i−n 
′
 ]。

也就是说,sss 中长度为 n′n'n 
′
  的前缀就是 s′s's 
′
 ,并且在这之后的每一个位置上的字符 s[i]s[i]s[i],都需要与它之前的第 n′n'n 
′
  个字符 s[i−n′]s[i-n']s[i−n 
′
 ] 相同。

因此,我们可以从小到大枚举 n′n'n 
′
 ,并对字符串 sss 进行遍历,进行上述的判断。注意到一个小优化是,因为子串至少需要重复一次,所以 n′n'n 
′
  不会大于 nnn 的一半,我们只需要在 [1,n2][1, \frac{n}{2}][1, 
2
n
​
 ] 的范围内枚举 n′n'n 
′
  即可。

参考代码:

__459重复的子字符串_枚举

java 复制代码
package 代码随想录.字符串;

public class __459重复的子字符串_枚举 {
    //给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
    /**
    方法一: 双重for循环,其中一个for循环,用i,j记录起始,截止位置;;另一个for循环,用于剩余的j到结尾。
     */
    public boolean repeatedSubstringPattern(String s) {
        /*
        提示:
            1 <= s.length <= 104
            s 由小写英文字母组成
        解法1:调用KMP算法/暴力for循环?,将一个部分,分成从[0,i]和[i+1,s.length-1]的两个子串。
         */
        int n = s.length();
        for (int i = 1;i*2 <= n;i++){   //要能够匹配,最多只能遍历一般即可。
            if (n % i == 0){    //把i作为匹配对象
                boolean match = true;
                for (int j = i;j < n;j++){     //j是匹配位置
                    if (s.charAt(j)!= s.charAt(j-i)){   //同步j-i位置。【i为配对对象】
                        match = false;
                        break;
                    }
                }
                if (match){
                    return true;
                }
            }
        }
        return false;
    }
}

__459重复的子字符串_字符串匹配

java 复制代码
package 代码随想录.字符串;

public class __459重复的子字符串_字符串匹配 {
    /**
     * 调用方法进行配对
     *
     * @param s
     * @return
     */
    public boolean repeatedSubstringPattern(String s){
       return (s+s).indexOf(s,1) != s.length();
    }
}

__459重复的子字符串_KMP算法

java 复制代码
package 代码随想录.字符串;

import java.util.Arrays;

public class __459重复的子字符串_KMP算法 {
    public boolean repeatedSubstringPattern(String s) {
        //确定一个固定的长度的字符串,去kmp配对另一个相同长度的字符串。
        return myKMP(s+s,s);    //这道题的原本是判别s是否是由某组字符重复构成
    }

    /**
     *
     * @param query
     * @param pattern
     * @return
     */
    private boolean myKMP(String query, String pattern) {
        int n = query.length();
        int m = pattern.length();
        int  [] fail = new int[m];
        Arrays.fill(fail,-1);
        for (int i = 1;i<m;i++){
            int j = fail[i-1];
            while (j != -1 && pattern.charAt(j+1)!= pattern.charAt(i)){
                j = fail[j];
            }
            if (pattern.charAt(j+1) == pattern.charAt(i)){
                fail[i] = j +1;
            }
        }
        int match = -1;
        for (int i = 1;i<n-1;i++){
            while (match != -1 && pattern.charAt(match + 1) != query.charAt(i)){
                match = fail[match];
            }
            if (pattern.charAt(match + 1) == query.charAt(i)){
                match++;
                if (match == m-1){
                    return true;
                }
            }
        }
        return false;
    }
}

__459重复的子字符串_优化的KMP算法

java 复制代码
package 代码随想录.字符串;

import java.util.Arrays;

public class __459重复的子字符串_优化的KMP算法 {
    public boolean repeatedSubstringPattern(String s) {
        //确定一个固定的长度的字符串,去kmp配对另一个相同长度的字符串。
        return myKMP(s);    //这道题的原本是判别s是否是由某组字符重复构成
    }

    /**
     *
     * @param pattern
     * @return
     */
    private boolean myKMP(String pattern) {
       int n = pattern.length();
       int [] fail = new int[n];
       Arrays.fill(fail,-1);
       for (int i = 1;i<n;i++) {
           int j = fail[i-1];
           while (j!= -1 && pattern.charAt(j+1)!= pattern.charAt(i)){
               j = fail[j];
           }
           if (pattern.charAt(j+1) == pattern.charAt(i)){
               fail[i] = j +1;
           }
       }
       return fail[n-1] != -1 && n%(n- fail[n-1] - 1) == 0 ;
    }

}

错误经验吸取

相关推荐
萝卜兽编程1 分钟前
优先级队列
c++·算法
Bucai_不才3 分钟前
【数据结构】树——链式存储二叉树的基础
数据结构·二叉树
2202_754421548 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
JH30739 分钟前
Oracle与MySQL中CONCAT()函数的使用差异
数据库·mysql·oracle
盼海9 分钟前
排序算法(四)--快速排序
数据结构·算法·排序算法
蓝染-惣右介10 分钟前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
冷心笑看丽美人12 分钟前
Spring框架特性及包下载(Java EE 学习笔记04)
数据库
一直学习永不止步24 分钟前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
努力的悟空35 分钟前
国土变更调查拓扑错误自动化修复工具的研究
运维·自动化
运维&陈同学1 小时前
【zookeeper03】消息队列与微服务之zookeeper集群部署
linux·微服务·zookeeper·云原生·消息队列·云计算·java-zookeeper