FZU2218 Simple String Problem(状压DP)
首先,定义S,表示前k个字符出现的集合,用二进制来压缩。
接下来,推出dp1[S],表示集合为S的子串的最长长度。
然后根据dp1[S]再推出dp2[S],表示集合为S或S的子集的子串的最长长度。
最后答案就是max(dp2[S]*dp2[补(S)])
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int d[1<<16]; 6 int main(){ 7 int t,n,k; 8 char str[2222]; 9 scanf("%d",&t); 10 while(t--){ 11 scanf("%d%d%s",&n,&k,str); 12 memset(d,0,sizeof(d)); 13 for(int i=0; i<n; ++i){ 14 int s=0; 15 for(int j=i; j<n; ++j){ 16 s|=1<<str[j]-'a'; 17 d[s]=max(d[s],j-i+1); 18 } 19 } 20 for(int i=0; i<(1<<k); ++i){ 21 for(int j=0; j<k ;++j){ 22 if((i>>j)&1) d[i]=max(d[i],d[i&(~(1<<j))]); 23 } 24 } 25 int res=0; 26 for(int i=0; i<(1<<k); ++i){ 27 res=max(res,d[i]*d[(~i)&((1<<k)-1)]); 28 } 29 printf("%d\n",res); 30 } 31 return 0; 32 }