题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2631
题意:
输入一个字符串,问最少可以将它划分成多少个回文串。
思路:
可以设置dp[i]为从第一个字符到第i个字符之间最少可以划分的回文串,然后设1<=j<=i,如果s[j+1]~s[i]是回文串那么dp[i]=min(dp[j]+1)
O(n的三次方)写法,20ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=1010;
char s[maxn];
int dp[maxn];
int len;
bool check(int a, int b)
{
int left=a, right=b;
while(a<b)
{
if(s[a]!=s[b])
return false;
a++; b--;
}
return true;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%s", s+1);
len=strlen(s+1);
memset(dp, 0, sizeof(dp));
for(int i=1; i<=len; i++)
{
dp[i]=i+1;
for(int j=1; j<=i; j++)
if(check(j, i))
dp[i]=min(dp[i], dp[j-1]+1);
}
printf("%d\n", dp[len]);
}
return 0;
}
O(n方)写法,事先打表将回文串标记,30ms。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=1010;
bool wtf[maxn][maxn];
int dp[maxn];
char s[maxn];
int len;
void init()
{
memset(wtf, 0, sizeof(wtf));
for(int i=1; i<=len; i++)
wtf[1][i]=true;
if(len==1)
return;
for(int i=1; i<len; i++)
if(s[i]==s[i+1])
wtf[2][i]=true;
for(int i=3; i<=len; i++)
for(int j=1; j<=len-i+1; j++)
if(s[j]==s[j+i-1]&&wtf[i-2][j+1])
wtf[i][j]=true;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%s", s+1);
len=strlen(s+1);
init();
for(int i=1; i<=len; i++)
dp[i]=INF;
dp[0]=0;
for(int i=1; i<=len; i++)
{
for(int j=1; j<=i; j++)
if(wtf[j][i-j+1])
dp[i]=min(dp[i], dp[i-j]+1);
}
printf("%d\n", dp[len]);
}
return 0;
}
估计是数据比较弱,导致O(n方)的写法比O(n的三次方)要慢。。。