0
先说一下这道题的题意,就是说给你一串字符串,n表示字符串的长度,k表示串中只包含字母表中前k个字母,并且都为小写,让你在长度为n的输入串中选择两个连续的子串,不能相交,并且在第一个子串中的字母在第二个子串中都没出现,即两个子串不含有相同字母,求成两个子串长度乘积的最大值。
这一题先是无从下手,网上说是状态压缩dp,没听懂,以前没做过这方面的题。所以沉寂了好久。但是我想不会做咱们就穷举不就得了,心想会超时,但试了一下,压着时间过了!所以穷举也是要技巧的,有技巧的穷举其实效率还是蛮高的。思路是这样的! 代码已经注释看一下喽
//其实输入的字符串最后是要分成两部分,记为0串与1串 //即输入的字符串中的字符分为两个集合,用0, 1表示 # include <cstdio> using namespace std; char s[2010];//存储输入的原串 int status[20];//表示状态,s[i]=1表示字母表中第i个字母在1串中 int change[2010];//将s字符串转化成0,1串 int n, k;//n, k的表示跟题目中一样 int ans; int max1_s[2010], max0_s[2010]; //max1_s[i]表示change数组中到以第i个1结尾的最大长度 //max0_s[i]表示change数组中到以第i个0结尾的最大长度 int max0, max1;//记录max1_s[i],max0_s[i]最大值 void func(int b){//b从0开始 if(b==k){//到达k,递归终止 max0=0;max1=0; for(int i=0; i<=n-1; i++){ change[i+1]=status[s[i]-96]; } max1_s[0]=0;max0_s[0]; for(int i=1; i<=n; i++){ if(change[i]){//change[i]==1 max1_s[i]=max1_s[i-1]+1;//加上前一个长度 max0_s[i]=0;//目前为一,初始化为0 if(max1_s[i]>max1){//更新最大值 max1=max1_s[i]; } } else{//change[i]==0 max0_s[i]=max0_s[i-1]+1;//加上前一个长度 max1_s[i]=0;//目前为一,初始化为0 if(max0_s[i]>max0){//更新最大值 max0=max0_s[i]; } } } if(max0*max1>ans){ ans=max0*max1; } } else{ //以下对status[i]的赋值是对于选与不选经行赋值的 status[b]=0; func(b+1); status[b]=1; func(b+1); } } int main(){ int i, j, t; scanf("%d", &t);//测试数据的组数 for(i=1; i<=t; i++){ scanf("%d%d", &n, &k); getchar(); scanf("%s", s); ans=0; func(0); printf("%d\n", ans); } return 0; }