【區間 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] 表示字符串 str[i:j]str[i:j] 中段式迴文串的最大長度。
  • 思考初始化:
    • f[0][0]=1f[0][0] = 1 表示單個字符的段式迴文長度爲 1
  • 思考狀態轉移方程
    • 如果 str[s:s+l]=str[el,e]str[s:s+l] = str[e-l, e]f[i][j]=max(1,dfs(s+l,el)+2)f[i][j] = max(1, dfs(s+l, e-l)+2)
  • 思考輸出f[0][n1]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(n2)O(n^2)
  • 空間複雜度:O(n2)O(n^2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章