classSolution { public: booljudge(const string& text, int l1, int l2, int len){ while (len --) { if (text[l1] != text[l2]) { returnfalse; } ++l1; ++l2; } returntrue; } intlongestDecomposition(string text){ int n = text.size(); int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (judge(text, l, r - len + 1, len)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; } };
classSolution { publicintlongestDecomposition(String text) { intn= text.length(); intres=0; intl=0, r = n - 1; while (l <= r) { intlen=1; while (l + len - 1 < r - len + 1) { if (judge(text, l, r - len + 1, len)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
publicbooleanjudge(String text, int l1, int l2, int len) { while (len > 0) { if (text.charAt(l1) != text.charAt(l2)) { returnfalse; } ++l1; ++l2; --len; } returntrue; } }
publicclassSolution { publicintLongestDecomposition(string text) { int n = text.Length; int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (Judge(text, l, r - len + 1, len)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
publicboolJudge(string text, int l1, int l2, int len) { while (len > 0) { if (text[l1] != text[l2]) { returnfalse; } ++l1; ++l2; --len; } returntrue; } }
booljudge(constchar* text, int l1, int l2, int len) { while (len --) { if (text[l1] != text[l2]) { returnfalse; } ++l1; ++l2; } returntrue; }
intlongestDecomposition(char * text){ int n = strlen(text); int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (judge(text, l, r - len + 1, len)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
classSolution: deflongestDecomposition(self, text: str) -> int: i, j = 0, len(text)-1 count = 0 left = '' right = '' while i <= j: left += text[i] right = text[j] + right if i == j: break else: if left == right: left = '' right = '' count += 2 i += 1 j -= 1 if left != ''and right != '': count += 1 return count
var longestDecomposition = function(text) { const n = text.length; let res = 0; let l = 0, r = n - 1; while (l <= r) { let len = 1; while (l + len - 1 < r - len + 1) { if (judge(text, l, r - len + 1, len)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
funclongestDecomposition(text string)int { iflen(text) == 1 { return1 } k := 0 str := text forlen(str) > 0 { l := 1 r := len(str)-1 for l <= r { if str[:l] == str[r:] { k += 2 str = str[l:r] break } l++ r-- } if l > r && len(str) > 0 { k++ break } } return k }
复杂度分析
时间复杂度:O(n^2),其中 n 为字符串 text 的长度,用「双指针」判断两字符串是否相等的时间复杂度为 O(n),需要判断 O(n) 次,所以总的时间复杂度为 O(n^2)。
空间复杂度:O(1),仅使用常量空间。
方法二:滚动哈希
思路与算法
在「方法一」的实现过程中,我们可以对字符串 text 进行「滚动哈希」预处理,这样在对于字符串判断某一个长度的前后缀是否相同时,可以在 O(1) 时间得到前后缀的哈希值进行判断。
intlongestDecomposition(string text){ init(text); int n = text.size(); int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (getHash(l, l + len - 1) == getHash(r - len + 1, r)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; } };
publicintlongestDecomposition(String text) { init(text); intn= text.length(); intres=0; intl=0, r = n - 1; while (l <= r) { intlen=1; while (l + len - 1 < r - len + 1) { if (Arrays.equals(getHash(l, l + len - 1), getHash(r - len + 1, r))) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
publicclassSolution { long[] pre1; long[] pre2; long[] pow1; long[] pow2; constint MOD1 = 1000000007; constint MOD2 = 1000000009; int base1, base2; Random random = new Random();
publicintLongestDecomposition(string text) { Init(text); int n = text.Length; int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (Enumerable.SequenceEqual(GetHash(l, l + len - 1), GetHash(r - len + 1, r))) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
intlongestDecomposition(char * text) { int n = strlen(text); longlong pre1[n + 1], pre2[n + 1]; longlong pow1[n], pow2[n]; init(text, n, pre1, pre2, pow1, pow2); int res = 0; int l = 0, r = n - 1; while (l <= r) { int len = 1; while (l + len - 1 < r - len + 1) { if (getHash(l, l + len - 1, pre1, pre2, pow1, pow2) == getHash(r - len + 1, r, pre1, pre2, pow1, pow2)) { res += 2; break; } ++len; } if (l + len - 1 >= r - len + 1) { ++res; } l += len; r -= len; } return res; }
复杂度分析
时间复杂度:O(n),其中 n 为字符串 text 的长度,预处理字符串哈希的时间复杂度为 O(n),双指针的时间复杂度为 O(n)。