File tree Expand file tree Collapse file tree 1 file changed +41
-1
lines changed Expand file tree Collapse file tree 1 file changed +41
-1
lines changed Original file line number Diff line number Diff line change @@ -390,6 +390,8 @@ public:
390390
391391### Java:
392392
393+ (版本一) 前缀表 减一
394+
393395```java
394396class Solution {
395397 public boolean repeatedSubstringPattern(String s) {
@@ -420,6 +422,45 @@ class Solution {
420422}
421423```
422424
425+ (版本二) 前缀表 不减一
426+
427+ ``` java
428+ /*
429+ * 充分条件:如果字符串s是由重复子串组成的,那么它的最长相等前后缀不包含的子串一定是s的最小重复子串。
430+ * 必要条件:如果字符串s的最长相等前后缀不包含的子串是s的最小重复子串,那么s必然是由重复子串组成的。
431+ * 推得:当字符串s的长度可以被其最长相等前后缀不包含的子串的长度整除时,不包含的子串就是s的最小重复子串。
432+ *
433+ * 时间复杂度:O(n)
434+ * 空间复杂度:O(n)
435+ */
436+ class Solution {
437+ public boolean repeatedSubstringPattern (String s ) {
438+ // if (s.equals("")) return false;
439+ // 边界判断(可以去掉,因为题目给定范围是1 <= s.length <= 10^4)
440+ int n = s. length();
441+
442+ // Step 1.构建KMP算法的前缀表
443+ int [] next = new int [n]; // 前缀表的值表示 以该位置结尾的字符串的最长相等前后缀的长度
444+ int j = 0 ;
445+ next[0 ] = 0 ;
446+ for (int i = 1 ; i < n; i++ ) {
447+ while (j > 0 && s. charAt(i) != s. charAt(j)) // 只要前缀后缀还不一致,就根据前缀表回退j直到起点为止
448+ j = next[j - 1 ];
449+ if (s. charAt(i) == s. charAt(j))
450+ j++ ;
451+ next[i] = j;
452+ }
453+
454+ // Step 2.判断重复子字符串
455+ if (next[n - 1 ] > 0 && n % (n - next[n - 1 ]) == 0 ) { // 当字符串s的长度可以被其最长相等前后缀不包含的子串的长度整除时
456+ return true ; // 不包含的子串就是s的最小重复子串
457+ } else {
458+ return false ;
459+ }
460+ }
461+ }
462+ ```
463+
423464### Python:
424465
425466(版本一) 前缀表 减一
@@ -930,4 +971,3 @@ bool repeatedSubstringPattern(char* s) {
930971<a href="https://programmercarl.com/other/kstar.html" target="_blank">
931972 <img src="../pics/网站星球宣传海报.jpg" width="1000"/>
932973</a>
933-
You can’t perform that action at this time.
0 commit comments