給定長度 ≤16 的字符串,每步可刪除一個子序列(不要求連續),只要該子序列是回文。求刪空整個字符串的最少步數。
ispal[mask]dp[mask]:刪除 mask 所代表字符集合所需最少步數。
dp[0] = 0,其餘 INFmask 從 1 到 (1<ispal[mask],dp[mask] = 1sub ⊂ mask:dp[mask] = min(dp[mask], dp[sub] + dp[mask^sub])
for (int sub = (mask-1) & mask; sub; sub = (sub-1) & mask) {
if (ispal[sub]) // 可選剪枝
dp[mask] = min(dp[mask], dp[sub] + dp[mask^sub]);
}
bool isPal(int mask) {
string t;
for (int i = 0; i < n; ++i)
if (mask & (1<<i)) t += s[i];
for (int i = 0, j = t.size()-1; i < j; ++i, --j)
if (t[i] != t[j]) return false;
return true;
}
int dfs(int mask) {
if (dp[mask] != INF) return dp[mask];
if (ispal[mask]) return dp[mask] = 1;
for (int sub = (mask-1) & mask; sub; sub = (sub-1) & mask)
if (ispal[sub])
dp[mask] = min(dp[mask], dfs(sub) + dfs(mask^sub));
return dp[mask];
}
Input: abb
子集 {a} {b} {b} 均回文
{a,b,b} 非回文
最優分割:{a} + {b,b} → 2 步