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 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文地址:https://www.cnblogs.com/rookiez/p/13341074.html