1234F

传送门

题意:
给出一个只含 a~t 的字符串,现在可以选择一段区间进行翻转,问区间中字符各不相同时,最长长度为多少。

分析:
将题意转换为选择两个字符各不相同的区间,然后长度相加取最大;
字符串中满足条件的所有区间长度和不超过20∗n,那么处理出所有区间,现在任务即为找到两个区间,其字符各不相同,且长度和最大;

dp[i] 代表,最多(至多)出现这些字符 的 连续串 的 最大长度
i是二进制状态枚举

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+5;;
const int inf=0x3f3f3f3f;
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
LL read()
{
    LL x=0,t=1;
    char ch=getchar();
    while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
    while(isdigit(ch)){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*t;
}
int f[(1<<20)+5];
char s[N];
int main()
{
    scanf("%s",s);
    int n=strlen(s);
    int lim=(1<<20)-1;
    for(int i=0;i<n;i++)
    {
        int t=0;
        for(int j=i;j<n;j++)
        {
            int v=s[j]-'a';
            if(t&(1<<v) ) break;
            t|=1<<v;
            f[t]=j-i+1;  ///不重复连续串的最长长度,不懂试着模拟
            //printf("%d
",f[t] );
        }
    }
    for(int i=0;i<20;i++)
        for(int j=0;j<=lim;j++)
            if( (j&(1<<i) )==0)
                f[j|(1<<i)]=max(f[j|(1<<i)],f[j] );///如果s中没有这些连续串,那么就等于f[j],便于后面通过互斥快速算答案
    int ans=0;
    for(int i=0;i<=lim;i++)
        ans=max(ans,f[i]+f[lim-i] );
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/DeepJay/p/12025195.html