Cho chuỗi s, cắt thành các chuỗi con palindrome. Tìm số lần cắt tối thiểu.
Ví dụ
s = "ababba" → Cắt: "aba|bb|a" → 2 lần cắt.
Thuật toán: DP + Kiểm tra palindrome
res[i] = số cắt tối thiểu cho chuỗi con .
res[n] = -1(cơ sở: chuỗi rỗng cần -1 cắt để công thức1 + res[j+1]cho 0 cắt).- Duyệt
itừn-1xuống0:res[i] = n - i - 1(cắt từng ký tự).- Với mỗi
jtừiđếnn-1: nếulà palindrome →res[i] = min(res[i], 1 + res[j+1]).
Kiểm tra palindrome
Hàm isPalindrome dùng 2 con trỏ left, right so sánh từ 2 đầu.
Cài đặt C++
#include <bits/stdc++.h>
using namespace std;
bool isPalindrome(string A) {
int left = 0, right = A.size() - 1;
while (left < right) {
if (A[left] != A[right]) return false;
left++; right--;
}
return true;
}
int solve(string A) {
int n = A.size();
vector<int> res(n + 1);
res[n] = -1;
for (int i = n - 1; i >= 0; i--) {
res[i] = n - i - 1;
for (int j = i; j < n; j++) {
if (isPalindrome(A.substr(i, j - i + 1))) {
res[i] = min(res[i], 1 + res[j + 1]);
}
}
}
return res[0];
}
class Solution {
public:
int minCut(string s) { return solve(s); }
};
int main() {
Solution ob;
cout << ob.minCut("ababba");
return 0;
}
Độ phức tạp
- Thời gian:
O(n^3)—O(n^2)cặp(i,j), mỗi lần check palindromeO(n). - Không gian:
O(n).
Tối ưu: Tiền tính bảng isPal[i][j] trong O(n^2) → tổng O(n^2).
Input / Output
Input: "ababba" Output: 2