51nod1154(回文串划分)

xiaoxiao2021-02-28  87

题目链接:https://www.51nod.com/onlineJudge/submitDetail.html#!judgeId=307682

无从下手的时候考虑DP……

区间DP考虑优化成线性DP……

统计回文串,可以枚举中点,想两边扩展……

预处理出以每个字符为结尾的最长回文串,记录其起点;对于每一个字符来说,枚举以这个字符为终点的回文串,选最小值。

#include <iostream> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int maxn = 5000 + 10; const int INF = (1<<31)-1; char a[maxn]; int f[maxn]; bool s[maxn][maxn]; vector<int> prv[maxn]; bool check(int s, int t){ for (int i=s; i<=(s+t)/2; i++){ if (a[i] != a[s+t-i]){ return false; } } return true; } int main() { scanf("%s", a); int len = strlen(a); for (int i=0; i<len; i++){ //预处理长度为奇数的回文串 int l = i; int r = i; while (l >= 0 && r < len && a[l] == a[r]){ prv[r].push_back(l); l--; r++; } } for (int i=0; i<len; i++){ //预处理长度为偶数的回文串 int l = i; int r = i + 1; while (l >= 0 && r < len && a[l] == a[r]){ prv[r].push_back(l); l--; r++; } } f[0] = 1; //线性DP for (int i=1; i<len; i++){ f[i] = INF; for (int k=0; k<prv[i].size(); k++){ f[i] = min(f[i], f[prv[i][k]-1]+1); } } cout << f[len-1] << endl; return 0; }

转载请注明原文地址: https://www.6miu.com/read-45694.html

最新回复(0)