FZU 2218 Simple String Problem

来源:互联网 发布:云计算市场规模 编辑:程序博客网 时间:2024/05/16 05:06

题目大意:

  给你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;}




0 0