【区间 dp】A015_LC_段式回文(两边紧逼法)

一、Problem

段式回文 其实与 一般回文 类似,只不过是最小的单位是 一段字符 而不是 单个字母。

举个例子,对于一般回文 “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}。

输入:text = "ghiabcdefhelloadamhelloabcdefghi"
输出:7
解释:我们可以把字符串拆分成 "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)"。

提示:

text 仅由小写英文字符组成。
1 <= text.length <= 1000

二、Solution

方法一:记忆化搜索

  • 定义状态
    • f [ i ] [ j ] f[i][j] 表示字符串 s t r [ i : j ] str[i:j] 中段式回文串的最大长度。
  • 思考初始化:
    • f [ 0 ] [ 0 ] = 1 f[0][0] = 1 表示单个字符的段式回文长度为 1
  • 思考状态转移方程
    • 如果 s t r [ s : s + l ] = s t r [ e l , e ] str[s:s+l] = str[e-l, e] f [ i ] [ j ] = m a x ( 1 , d f s ( s + l , e l ) + 2 ) f[i][j] = max(1, dfs(s+l, e-l)+2)
  • 思考输出 f [ 0 ] [ n 1 ] f[0][n-1]
class Solution {
	int n, f[][];
	String str;
	int dfs(int s, int e) {
		if (s > e)
			return 0;
        if (s == e)
            return 1;
		if (f[s][e] != 0)
			return f[s][e];
		int len = 1;
		for (int l = 1; l <= (e-s+1)/2; l++) {
			String beg = str.substring(s, s+l), end = str.substring(e-l+1, e+1);
			if (beg.equals(end)) {
				len = Math.max(len, dfs(s+l, e-l)+2);
            }
		}
		return f[s][e] = len;
	}
    public int longestDecomposition(String text) {
    	str = text;
    	n = str.length();
        f = new int[n][n];
        f[0][0] = 1;
    	dfs(0, n-1);
        return f[0][n-1];
    }
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2)
  • 空间复杂度: O ( n 2 ) O(n^2)

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/106859076