b_51_回文串划分(预处理+dp)
有一个字符串S,求S最少可以被划分为多少个回文串。例如:abbaabaa,有多种划分方式。
a|bb|aabaa - 3 个回文串
a|bb|a|aba|a - 5 个回文串
a|b|b|a|a|b|a|a - 8 个回文串
思路:f[i]表示子串s[0:i]最少可以划分为多少个回文串
优化:判断回文串可以用\(O(n^2)\)dp预处理
#include<bits/stdc++.h>
using namespace std;
const int N=5005;
int n,f[N],st[N][N]; //st[l][r]表示s[l:r]是否是回文;f[i]表示前i个字符可以最少划分为多少个回文串
char s[N];
void init_st() {
memset(st,false,sizeof st), st[0][0]=1;
for (int r=1; r<=n; r++)
for (int l=1; l<=r; l++) {
if (s[l]==s[r] && (r-l<2 || st[l+1][r-1]))
st[l][r]=1;
}
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>s+1;
n=strlen(s+1), init_st();
for (int i=1; i<=n; i++) f[i]=i;
for (int i=1; i<=n; i++)
for (int j=0; j<i; j++) if (st[j+1][i])
f[i]=min(f[i], f[j]+1);
cout<<f[n];
return 0;
}