描述
切割回文
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 10000;
int d[1005];
int ispa[1005][1005],vis[1005][1005];
char a[1010];
int l;
//int ispan(int s,int e){//正常判断 总复杂度O(n^3)
// int i = s;
// int j = e;
// while(i < j){
// if(a[i] == a[j]){
// ++i;
// --j;
// }
// else
// break;
// }
// if(i >= j)
// return 1;
// else
// return 0;
//}
void getispa(int l){//先求所有回文子串
int c,i,j;
memset(ispa,0,sizeof(ispa));
for(c = 1;c <= l; ++c){
ispa[c][c] = 1;
i = c - 1;
j = c;
while(i >= 1 && j <= l && a[i] == a[j]){
ispa[i][j] = 1;
--i;
++j;
}
i = c - 1;
j = c + 1;
while(i >= 1 && j <= l && a[i] == a[j]){
ispa[i][j] = 1;
--i;
++j;
}
}
}
//int ispan(int s,int e){//使用dp ,方法来自紫书
// if(s >= e)
// return 1;
// if(a[s] != a[e])
// return 0;
// if(vis[s][e])
// return ispa[s][e];
// vis[s][e] = 1;
// ispa[s][e] = ispan(s + 1,e - 1);
// return ispa[s][e];
//}
int main(){
//freopen("d://poj//data.txt","w",stdout);//udebug
int n,i,j;
scanf("%d",&n);
for(int p = 0;p < n; ++p){
scanf("%s",a + 1);
l = strlen(a + 1);
memset(vis,0,sizeof(vis));
getispa(l);
d[0] = 0;
for(i = 1;i <= l; ++i){
d[i] = INF;
for(j = i;j > 0; --j){
if(ispa[j][i]){
int t = d[j - 1] + 1;
if(t < d[i])
d[i] = t;
}
}
}
printf("%d\n",d[l]);
}
return 0;
}
和照明系统差不多的思路。亮点是回文求解上的减少时间复杂度。