Palindrome Partitioning LightOJ - 1044(回文串最小分割数,O(n^2)预处理子串是否回文)
题意:将一个字符串分割成最少的字符串,使得分割出的每个字符串都是回文串。输出最小的分割数。
方法(自己的):先O(n^2)(用某个点或某个空区间开始,每次向左右扩展各一个的方法)处理出所有子串是否回文。然后常规区间dp,ans[i][j]表示i到j的子串的最小划分数。如果i到j的子串本身为回文串,那么ans[i][j]为1,否则枚举所有方案将i到j划分为两个区间,取所有两个区间结果之和的最小值。
方法(其他,大概就是压了一下空间,压了一下时间的常数):http://blog.csdn.net/l123012013048/article/details/49475845
解题思路:用dp[i]表示前i个字符划分成回文串,需要划分成多少个部分
接着枚举j,如果[i,j]回文,那么dp[i] = min(dp[i], dp[j - 1] + 1)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 bool ok[1010][1010]; 6 char s[1010]; 7 int T,TT,len,ans[1010][1010]; 8 int get(int l,int r) 9 { 10 if(ans[l][r]) return ans[l][r]; 11 if(l==r) return 1; 12 if(ok[l][r]) return ans[l][r]=1; 13 int anss=0x3f3f3f3f,i; 14 for(i=l;i<r;i++) 15 if(ok[l][i]) 16 anss=min(anss,get(i+1,r)+1); 17 return ans[l][r]=anss; 18 } 19 int main() 20 { 21 int i,l,r; 22 bool now; 23 scanf("%d",&T); 24 for(TT=1;TT<=T;TT++) 25 { 26 scanf("%s",s+1); 27 len=strlen(s+1); 28 memset(ans,0,sizeof(ans)); 29 for(i=1;i<=len;i++) 30 for(l=i,r=i,now=1;l>=1&&r<=len;l--,r++) 31 { 32 if(s[l]!=s[r]) now=0; 33 ok[l][r]=now; 34 } 35 for(i=1;i<len;i++) 36 for(l=i,r=i+1,now=1;l>=1&&r<=len;l--,r++) 37 { 38 if(s[l]!=s[r]) now=0; 39 ok[l][r]=now; 40 } 41 printf("Case %d: %d\n",TT,get(1,len)); 42 } 43 return 0; 44 }