给你一个字符串 sequence ,如果字符串 word 连续重复 k 次形成的字符串是 sequence 的一个子字符串,那么单词 word 的 重复值为 k 。单词 word 的 最大重复值 是单词 word 在 sequence 中最大的重复值。如果 word 不是 sequence 的子串,那么重复值 k 为 0 。 给你一个字符串 sequence 和 word ,请你返回 最大重复值 k 。
迭代 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public int maxRepeating (String sequence, String word) { char [] seqArray = sequence.toCharArray(); char [] wordArray = word.toCharArray(); int result = 0 ; int n = seqArray.length - wordArray.length + 1 ; for (int i = 0 ; i < n; i++) { int s = i; int e = s + wordArray.length; int cnt = 0 ; while (e <= seqArray.length) { int j = s; for (; j < e; j++) { if (seqArray[j] != wordArray[j - s]) break ; } if (j == e) { cnt++; s = e; e += wordArray.length; } else { break ; } } if (cnt > result) result = cnt; } return result; } }
简单枚举 + 动态规划
KMP 算法 + 动态规划 方法一的数组 valid 本质上就是标记了字符串 word 在字符串 sequence 中所有出现的位置。而我们可以使用更高效的 KMP 算法 在 O (m+n) O (m+n) 的时间内得到数组 valid。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public int maxRepeating (String sequence, String word) { int n = sequence.length(), m = word.length(); if (n < m) { return 0 ; } int [] fail = new int [m]; Arrays.fill(fail, -1 ); for (int i = 1 ; i < m; ++i) { int j = fail[i - 1 ]; while (j != -1 && word.charAt(j + 1 ) != word.charAt(i)) { j = fail[j]; } if (word.charAt(j + 1 ) == word.charAt(i)) { fail[i] = j + 1 ; } } int [] f = new int [n]; int j = -1 ; for (int i = 0 ; i < n; ++i) { while (j != -1 && word.charAt(j + 1 ) != sequence.charAt(i)) { j = fail[j]; } if (word.charAt(j + 1 ) == sequence.charAt(i)) { ++j; if (j == m - 1 ) { f[i] = (i >= m ? f[i - m] : 0 ) + 1 ; j = fail[j]; } } } return Arrays.stream(f).max().getAsInt(); } }
复杂度分析
时间复杂度:O (m + n) O (m+n),其中 nn 和 mm 分别是字符串 sequence 和 word 的长度。
空间复杂度:O (m + n) O (m+n),即为 KMP 算法中的数组 fail 以及数组 f 需要使用的空间。
【字符串哈希】字符串哈希入门