Palindrome là xâu ký tự mà nếu đọc nó từ trái sang phải cũng như từ phải sang trái ta được cùng một xâu. Một xâu ký tự bất kỳ luôn có thể biểu diễn như là một dãy các palindrome nếu như ta coi xâu chỉ gồm một ký tự luôn là một palindrome. Ví dụ: xâu bobseesanna có thể biểu diễn dưới dạng dãy các palindrome theo nhiều cách, chẳng hạn:
Cho xâu ký tự $S$, cần tìm cách biểu diễn xâu dưới dạng một dãy gồm số ít nhất các palindrome. Ví dụ: cho bobseesanna, do ta có bobseesanna = bob + sees + anna và không thể biểu diễn bobseesanna bởi ít hơn là palindrome nên biểu diễn này chính là biểu diễn cần tìm.
Dữ liệu vào:
Dữ liệu ra:
Ví dụ:
// Input
bobseesanna
// Output
3
Giới hạn:
bool
có chỉ số $(i,j)$ thể hiện rằng liệu tổng của các kí tự từ $i$ tới $j$ có là palindrome không, điều kiện để tổng các kí tự từ $i$ đến $j$ là một palindrome là tổng các kí tự từ $i + 1$ đến $j - 1$ là palindrome và kí tự thứ $j$ và kí tự thứ $i$ phải bằng nhau.for (int i = 1; i<=n; i++) {
palin[i][i] = true;
int left = i - 1, right = i + 1;
while (left != 0 && right != n + 1) //Điều kiện đảm bảo left và right không bị chệch ra khỏi xâu
if (s[left] == s[right]) {
palin[left][right] = true;
left--;
right++;
}
else break;
if (s[i] == s[i+1]) { //Điều kiện xâu phải có tâm là 2 kí tự
palin[i][i+1] = true; //Hiển nhiên, tâm là một palindrome
left = i - 1;
right = i + 2;
while (left >= 1 && right <= n) { //Điều kiện đảm bảo left và right không bị chệch ra khỏi xâu
if (s[left] == s[right]) { //Kiểm tra 2 kí tự, nếu bằng nhau thì ghi lại kết quả
palin[left][right] = true;
left--; //Nếu là palindrome thì ta xét tiếp các xâu to hơn
right++;
} else break; //Nếu không bằng nhau tức là tổng các kí tự từ left tới right không phải palindrome, kết thúc vòng lặp bởi //nếu xét xâu sau thì điều kiện không được thoả mãn
}
}
}
Sau khi đã xây dựng được mảng kiểm tra, ta chỉ cần lắp lại vào thuật toán cũ là xong.
#include <bits/stdc++.h>
using namespace std;
char s[1005];
bool palin[1001][1001];
int f[1001];
int n;
int main()
{
scanf("%s", s + 1); //Đọc dữ liệu vào mảng char, bắt đầu từ 1
n = strlen(s + 1); //Lấy độ dài của mảng, tính từ 1
f[1] = 1;
for (int i = 1; i<=n; i++) {
palin[i][i] = true;
int left = i - 1, right = i + 1;
while (left != 0 && right != n + 1)
if (s[left] == s[right]) {
palin[left][right] = true;
left--;
right++;
}
else break;
if (s[i] == s[i+1]) {
palin[i][i+1] = true;
left = i - 1;
right = i + 2;
while (left >= 1 && right <= n) {
if (s[left] == s[right]) {
palin[left][right] = true;
left--;
right++;
} else break;
}
}
}
for (int i = 2; i<=n; i++) {
f[i] = f[i-1] + 1;
for (int j = i-1; j>= 1; j--)
if (palin[j][i] == true)
f[i] = min(f[i], f[j-1] + 1);
}
cout << f[n];
return 0;
}