思路:注意到k只有16,比较显然的想到状压DP,令dp[s]为s这个状态的最长长度,那么需要枚举反面的子集,显然复杂度会爆炸,有一个很巧妙的地方是将dp[s]表示为s这个状态及其子集的最长长度,这样可以大大减少复杂度,最终复杂度为O(n^2+k*2^k)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dp[1<<16];
char s[2005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&k);
scanf("%s",s);
for(int i = 0;i<n;i++)
{
int t = 0;
for(int j = i;j<n;j++)
{
t|=(1<<(s[j]-'a'));
dp[t]=max(dp[t],j-i+1);
}
}
for(int i = 0;i<(1<<k);i++)
for(int j = 0;j<k;j++)
if(i&(1<<j))
dp[i]=max(dp[i],dp[i^(1<<j)]);
int ans = 0;
for(int i = 0;i<(1<<k);i++)
ans = max(ans,dp[i]*dp[i^((1<<k)-1)]);
printf("%d\n",ans);
}
}