題目大意:
給一個字符串,每次可以刪除一個可不連續迴文子串,問最少刪幾次可以全部刪完。
思路:
因爲字符串長度最大16,所以可用二進制狀態表示, 1表示選取這個字符,0不選,組成一個子串。
先預處理出所有狀態,看這個狀態是不是迴文。
f[i]表示狀態i最少幾次可以全刪完, 初始化f數組INF
f[i] = min{f[i], f[s]+1 } s是i的子集。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
typedef long long int64;
const int INF = 0x3f3f3f3f;
const int MAXN = (1<<16)+10;
char str[20];
bool check[MAXN];
int f[MAXN];
int maxSta;
bool isPalind(int st, int len){
char sub[20];
int idx = 0;
for(int i=0; i<len; ++i){
if( (st>>i)&1 )
sub[idx++] = str[i];
}
for(int i=0; i<idx/2; ++i){
if(sub[i] != sub[idx-1-i])
return false;
}
return true;
}
int main(){
int T;
scanf("%d", &T);
check[0] = false;
while(T--){
scanf("%s", str);
int len = strlen(str);
maxSta = (1<<len)-1;
for(int i=1; i<=maxSta; ++i){
check[i] = isPalind(i, len);
}
memset(f, 0x7f, sizeof(f));
f[0] = 0;
for(int i=1; i<=maxSta; ++i){
for(int s=i; s; s=(s-1)&i)
if(check[s])
f[i] = min(f[i], f[i^s]+1);
}
printf("%d\n", f[maxSta]);
}
return 0;
}