1. 程式人生 > 實用技巧 >LeetCode1147 段式迴文

LeetCode1147 段式迴文

段式迴文 其實與 一般迴文 類似,只不過是最小的單位是 一段字元而不是 單個字母。

舉個例子,對於一般迴文 "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)"。

這個還是可以用動態規劃來解決,用dp[i]記錄到達i這個位置(對稱,所以只用處理左半部分)的最多的段數。

外層迴圈1-n/2,內層從已知的最大段數的位置left一直到外層位置,看能不能增加段數。

 1 class Solution {
 2 public:
 3     int longestDecomposition(string text) {
 4         int len=text.size();
 5         int left=0;
 6         int *dp=new
int[len/2+1]; 7 char* ch=(char*)text.c_str(); 8 for(int i=0;i<len/2+1;++i) 9 dp[i]=-1; 10 dp[0]=0; 11 12 for(int i=1;i<=len/2;++i){ 13 for(int j=left;j<i;++j){ 14 if(dp[j]==-1) continue; 15 if(!check(ch,j,i,len)) continue; 16 dp[i]=dp[j]+1; 17 left=i; 18 } 19 } 20 return max(1,dp[left]*2+(left*2==len?0:1)); 21 } 22 23 bool check(char* ch,int j,int i, int n){ 24 for(int m=j;m<i;++m){ 25 if(ch[m]!=ch[n-i+(m-j)]) return false; 26 } 27 return true; 28 } 29 };

還可以直接用雙指標+貪心解決。左指標移動到和有指標的位置的時候,比較pre-i和右指標開始往左相同長度的子串(pre為之前已經匹配到的最右位置)。如果能匹配就右指標往左移動,如果不能匹配就左指標繼續右移。結束迴圈的條件為左指標超過了右指標(一次匹配後右指標左移,發生在長度為偶數的情況下);或者左指標等於右指標(發生在奇數位的情況或者沒有匹配的情況下)。

 1 class Solution:
 2     def longestDecomposition(self, text: str) -> int:
 3         n = len(text)
 4         i, pre_i = 0, -1
 5         ans = 0
 6         j = n - 1
 7         while i <= j:    # 寫成while True也行
 8             while text[i] != text[j]:   # 一定會結束
 9                 i += 1
10             # print("i, j:",i, j)
11             if i == j:
12                 ans += 1
13                 break
14             elif i < j:
15                 l = i - pre_i
16                 flag = True
17                 for k in range(0, l):
18                     if text[j - k] == text[i - k]:
19                         continue
20                     else:
21                         flag = False
22                         break
23                 if flag:
24                     # 程式成功遍歷結束
25                     pre_i = i
26                     i += 1
27                     j = j - l
28                     ans += 2
29                 else:
30                     i += 1
31             else:
32                 break
33         return ans
34 
35 作者:horizonlc-codingMyHero
36 連結:https://leetcode-cn.com/problems/longest-chunked-palindrome-decomposition/solution/hen-jian-dan-de-jian-dan-bian-li-by-horizonlc-codi/
37 來源:力扣(LeetCode)
38 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。