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]更新答案。
给你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; }
相关文章推荐
- 奇怪的比赛
- linux下oracle 11.2.0.1升级到11.2.0.4
- C++ STL算法系列---copy函数
- 10、ROS记录和重现数据
- Android Studio 快捷键大全及使用技巧
- jQuery通过input标签的name获取值
- 第29章:线性规划
- 比酒量
- 《LeetBook》leetcode题解(16):3Sum Closest [M]
- c语言入门
- 在WinDBG中查看内存的命令
- 菜鸟nginx源代码剖析数据结构篇(八) 缓冲区链表ngx_chain_t
- mysql解压之后的安装
- Weblogic中可以使用的脚本
- HDFS的工作流程分析
- 案例:植物大战僵尸的基础界面
- CodeForces解题报告——4
- 第一次参与项目的idea
- C#中的事务用法实例分析
- Windows8下安装Docker