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 }
posted @ 2017-10-27 20:42  hehe_54321  阅读(207)  评论(0编辑  收藏  举报
AmazingCounters.com