标签:
d[i]表示前面i个字符划分成的最小回文串个数,那么转移i字符和之前的某个字符j构成回文串形成的新划分,所以要判断前面的字符j+1到i是不是回文串,可以用Manacher算法预处理出来。
#include <iostream> #include <algorithm> #include <cstring> #include<cstdio> using namespace std; const int MAX = 1042; int len, p[2*MAX]; char str[MAX], newstr[2*MAX]; bool isPal[MAX][MAX]; void change() { int i; newstr[0] = ‘@‘; newstr[1] = ‘#‘; for (i = 0; i < len; i++){ newstr[2*i + 2] = str[i]; newstr[2*i + 3] = ‘#‘; } newstr[2*len + 2] = ‘\0‘; return ; } #define toPre(x) ((x-1)>>1) void Manacher() { int i, j, id, maxid = 0; len = 2 * len + 2; for (i = 0; i < len; i++){ if (maxid > i){ p[i] = min(p[2*id - i], maxid - i); } else{ p[i] = 1; } while (newstr[i+p[i]] == newstr[i-p[i]]) p[i]++; if (p[i] + i > maxid){ maxid = p[i] + i; id = i; } } for( i = 1; i < len; i++){ char pivot = newstr[i]; p[i]--; for(j = !(pivot<=‘z‘&&pivot>=‘a‘); j < p[i]; j+=2){ int u = toPre(i-j),v = toPre(i+j); isPal[u][v] = true; } } } int d[MAX]; int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while (T--){ scanf("%s",str); len = strlen(str); change(); memset(isPal,0,sizeof(isPal)); Manacher(); len = (len-1)>>1; for(int i = 0; i < len; i++){ d[i] = isPal[0][i]?1:i+1; for(int j = 0; j < i; j++)if(isPal[j+1][i]){ d[i] = min(d[i],d[j]+1); } } printf("%d\n",d[len-1]); } // system("pause"); return 0; }
UVA 11584 Partitioning by Palindromes 划分回文串 (Manacher)
标签:
原文地址:http://www.cnblogs.com/jerryRey/p/4726739.html