難度hard
段式回文 其實與 一般回文 類似,只不過是最小的單位是 一段字符 而不是 單個字母。
舉個例子,對於一般回文 "abcba" 是回文,而 "volvo" 不是,但如果我們把 "volvo" 分為 "vo"、"l"、"vo" 三段,則可以認為 “(vo)(l)(vo)” 是段式回文(分為 3 段)。
給你一個字符串 text,在確保它滿足段式回文的前提下,請你返回 段 的 最大數量 k。
如果段的最大數量為 k,那么存在滿足以下條件的 a_1, a_2, ..., a_k:
每個 a_i 都是一個非空字符串;
將這些字符串首位相連的結果 a_1 + a_2 + ... + a_k 和原始字符串 text 相同;
對於所有1 <= i <= k,都有 a_i = a_{k+1 - i}。
示例 1:
輸入:text = "ghiabcdefhelloadamhelloabcdefghi"
輸出:7
解釋:我們可以把字符串拆分成 "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)"。
示例 2:
輸入:text = "merchant"
輸出:1
解釋:我們可以把字符串拆分成 "(merchant)"。
示例 3:
輸入:text = "antaprezatepzapreanta"
輸出:11
解釋:我們可以把字符串拆分成 "(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)"。
示例 4:
輸入:text = "aaa"
輸出:3
解釋:我們可以把字符串拆分成 "(a)(a)(a)"。
提示:
text 僅由小寫英文字符組成。
1 <= text.length <= 1000
解題思路:這道題可以說解題思路是相對直接的,沒有那么難,就是用兩個指針pre和cur指示左半部分應該截取的子字符串的兩個坐標,同時用總字符串的長度減去這兩個指針len-cur和len-pre用於指示右半部分應該截取的子字符串的坐標,然后將截出來的兩段字符串進行比較,如果相等,那更新指針位置,pre=cur,同時更新結果res。注意不管兩個字符串相等不相等,cur是一直在前進的,直到到達字符串中點,其實這本質上也是一種貪心策略,就是不斷地嘗試,一步步走,只要滿足條件,就更新結果,把段數加上去。當退出while循環的時候,還需要再加一個操作,如果len是奇數,那說明中間肯定有一段字符串,沒有被統計進來,因此結果應該加一,如果len是偶數,有兩種情況:像"aaaa"這種,所有段數都被上一步囊括了,因此這種不做處理;另一種就是“aabcaa"這種,中間也有多的一個字符串,沒有被上面的策略包括,這種情況下我們要在res中加一,此時只要判斷pre指針是否小於len/2即可,因為前一種情況pre肯定能到達中點,而這種情況下則不行。
代碼 t42 s60 java
class Solution {
public int longestDecomposition(String text) {
int res = 0, len = text.length(), pre = 0, cur = 1;
if(len==1) return 1;
while(cur<=len/2){
// System.out.println(text.substring(pre, cur));
// System.out.println(text.substring(len-cur, len-pre));
if(text.substring(pre, cur).equals(text.substring(len-cur, len-pre))){
res += 2;
pre = cur;
}
cur++;
}
if(len%2==1 || pre<len/2) res++;
return res;
}
}
下面有cpp的代碼,思路差不多,供參考。
代碼 t100 s70 cpp
class Solution {
public:
int longestDecomposition(string text) {
int sz = text.size(), pre = 0, res = 0;
for(int i=0; i<sz/2; i++){
if(text.substr(pre, i-pre+1)==text.substr(sz-i-1, i-pre+1)){
res += 2;
pre = i+1;
}
}
if(sz%2==1 || pre<sz/2) res++;
return res;
}
};
參考資料: