您的位置:首页 > 其它

FZU 2218 Simple String Problem

2016-04-19 21:28 351 查看
题目大意:

给你n个字符,这n个字符是由字母表前k个字符组成的。问两个区间,

这两个区间所含字符种类不同,输出两个区间最大乘积。

令b[ sta ]为sta所能取的最大值,dp[ sta ]为sta及其子集所能取的最大值,

转移方程 dp[ sta]=max(b[sta],dp[ sta最大真子集 ])。

那么sta^(1<<k-1)就代表sta的补集。用dp[state]*dp[((1<<k)-1)^state]更新答案。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<cstring>
#include<queue>
#include<stack>
#include<list>

using namespace std;

typedef long long ll;
const int MAXN=100000;
const ll INF=1e9;
const ll mod=1e9+7;

int b[MAXN],dp[MAXN];

int main()
{
//freopen("A-large.in","r",stdin);
//freopen("A-large.out","w",stdout);
int t;
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
string s;
cin>>s;
memset( b,0,sizeof(b) );
for(int i=0;i<n;i++){
int sta=0;
for(int j=i;j<n;j++){
sta=sta|( 1<<(s[j]-'a') );
b[ sta ]=max( b[sta],j-i+1 );
}
}
for(int i=1;i<(1<<k);i++){
dp[i]=b[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=1;i<(1<<k);i++){
ans=max( ans,dp[i]*dp[i ^( (1<<k)-1) ] );
}
printf("%d\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: