问题:
You are given a string ss consisting only of first 2020 lowercase Latin letters ('a', 'b', ..., 't').
Recall that the substring s[l;r]s[l;r] of the string ss is the string slsl+1…srslsl+1…sr . For example, the substrings of "codeforces" are "code", "force", "f", "for", but not "coder" and "top".
You can perform the following operation no more than once: choose some substring s[l;r]s[l;r] and reverse it (i.e. the string slsl+1…srslsl+1…sr becomes srsr−1…slsrsr−1…sl ).
Your goal is to maximize the length of the maximum substring of ss consisting of distinct (i.e. unique) characters.
The string consists of distinct characters if no character in this string appears more than once. For example, strings "abcde", "arctg" and "minecraft" consist of distinct characters but strings "codeforces", "abacaba" do not consist of distinct characters.
Input
The only line of the input contains one string ss consisting of no more than 106106 characters 'a', 'b', ..., 't' (first 2020 lowercase Latin letters).
Output
Print one integer — the maximum possible length of the maximum substring of ss consisting of distinct characters after reversing no more than one its substring.
Examples
Input
abacaba
Output
3
Input
abcdecdf
Output
6
Input
aabbcc
Output
3
Input
abcdeefc
Output
6
题意:给一个字符串,你可以反转任意一个子串,只能反转一次,找到一个最长不同字母子串的长度;
思路:利用二进制进行储存,a b c d e f g h i j k l m n o p q r s t
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
状态转移方程:maxx=max(maxx,dp[(1<<20)-1-i]+dp[i]);
1<<20-1-i表示它的相反状态
看代码:
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; int book[1<<21],dp[1<<21]; char s[1001000]; //利用二进制解决 //a b c d e f g h i j k l m n o p q r s t //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 //1<<20-1-i表示它的相反状态 int main() { scanf("%s",&s); int d=strlen(s); memset(dp,0,sizeof(dp)); for(int i=0; i<d; i++)//把所有的状态都存起来 { int ans=0,num=0;//ans记录状态,num记录不同字母的个数 for(int j=i; j<d; j++)//不会超时,最多跑20次 { num++; int k=s[j]-97; if(ans&(1<<k))//判断重复字母,&只会返回1或0; break; ans=ans|(1<<k);//把没有出现过的字母加进去 dp[ans]=num;//标记这种状态; } } for(int i=0; i<20; i++) //为反转做处理,意思是把每一种状态没有的字母都补进去,但只是虚拟,并没有增加字母种类; for(int j=0; j<(1<<20); j++) { if(j&(1<<i)) continue; int kk=j|(1<<i); dp[kk]=max(dp[kk],dp[j]); } int maxx=0; for(int i=0; i<(1<<20); i++) maxx=max(maxx,dp[(1<<20)-1-i]+dp[i]);//1<<20-1-i表示它的相反状态 printf("%d\n",maxx); }