1. 程式人生 > >1154 回文串劃分(DP+Manacher)

1154 回文串劃分(DP+Manacher)

ref onclick 萬年 算法題 family -s import ros 劃分數

1154 回文串劃分 基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級算法題 有一個字符串S,求S最少可以被劃分為多少個回文串。 例如:abbaabaa,有多種劃分方式。 a|bb|aabaa - 3 個回文串 a|bb|a|aba|a - 5 個回文串 a|b|b|a|a|b|a|a - 8 個回文串 其中第1種劃分方式的劃分數量最少。 Input
輸入字符串S(S的長度<= 5000)。
Output
輸出最少的劃分數量。
Input示例
abbaabaa
Output示例
3
相關問題 最長回文子串 V2(Manacher算法) 最長回文子串 回文串劃分 V2 6 40 回文字符串 10 //顯然dp,dp[i] 表前 i 個數最少能變幾個回文 dp[i] = min(dp[i], dp[z-1]+1) "s[z],s[z+1]...s[i]" 是一個回文串 用馬拉車就是 n*2n ,5000*10000,話說弱雞我debug一萬年。。。 不用就是 n^3 吧,不大懂 技術分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4
#define MOD 1000000007 5 #define MX 5005 6 7 int n; 8 int len; 9 char temp[MX]; 10 char str[MX*2]; 11 int p[MX*2]; 12 int dp[MX*2]; 13 14 void Init() 15 { 16 len = 0; 17 str[len++]=@; 18 str[len++]=#; 19 n = strlen(temp); 20 for (int i=0;i<n;i++) 21 { 22 str[len++]=temp[i];
23 str[len++]=#; 24 } 25 memset(p,0,sizeof(p)); 26 } 27 28 void Manacher() 29 { 30 Init(); 31 int mx = 0, id =0; 32 for (int i=1;i<len;i++) 33 { 34 p[i] = mx>i ? min(p[2*id-i],mx-i):1; 35 while (str[i+p[i]]==str[i-p[i]]) p[i]++; 36 if (i+p[i]>mx) 37 { 38 mx = i+p[i]; 39 id = i; 40 } 41 } 42 } 43 44 int main() 45 { 46 while (scanf("%s",temp)!=EOF) 47 { 48 Manacher(); 49 50 for (int i=0;i<n;i++) 51 { 52 dp[i] = i+1; //初值 53 int pos = (i+1)*2; 54 for (int j=pos;j>=1;j--) 55 { 56 if(j+p[j]-2>=pos) 57 { 58 int pre = (j-(pos-j))/2-1; 59 if (pre==0) dp[i]=1; 60 else dp[i]= min(dp[pre-1]+1,dp[i]); 61 } 62 } 63 } 64 printf("%d\n",dp[n-1]); 65 } 66 return 0; 67 }
View Code

1154 回文串劃分(DP+Manacher)