Codeforces 1234 F. Sin embargo, otra inversa de subcadena (子 集 dp)

Enlace al
tema La idea principal del tema:
puede seleccionar una subcadena (o no puede seleccionarla) para invertir, y encontrar la subcadena más larga en la cadena después de la operación, donde se requiere que se repitan todos los caracteres de esta subcadena.

Ideas para resolver problemas:
Primero, puede simplificar el problema para seleccionar dos subcadenas, luego conectarlas sin repetir caracteres y luego averiguar la suma más larga de estas dos subcadenas, porque los caracteres en las dos subcadenas no se repiten para garantizar la posición No se cruzan, por lo que ya no tienes que pensar en la ubicación.
Establezca el estado dp [sta]: para indicar la longitud actual de la subcadena no repetitiva más larga en este estado y todos sus subconjuntos.
Por ejemplo: sta = 1010: significa {bd} y su subconjunto ∅, cuál es la longitud de la subcadena más larga de {b}, {d}.
Primero, para cada posición, encuentre violentamente una subcadena no repetitiva comenzando desde la posición actual, y luego guarde el estado, dp [sta] = len. El número máximo de cálculos es 1e6 * 20.

for (int i=1;i<=n;i++)
{
    int sum=0;
    for (int j=i;j<=n;j++)
    {
        if(sum&(1<<(s[j]-'a')))
        break;
        sum|=(1<<(s[j]-'a'));
        dp[sum]=j-i+1;
    }
}

Luego, la recursión es tomar la respuesta del subconjunto y el valor máximo de la respuesta en el subconjunto. El número de cálculos también es aproximadamente 1e6 * 20.

for(int i=0;i<(1<<20);i++)
{
    for (int j=0;j<20;j++)
    {
        if (i&(1<<j))
        dp[i]=max(dp[i],dp[i^(1<<j)]);
    }
}

Ahora dos subcadenas no repetitivas pueden considerarse como dos conjuntos disjuntos, luego enumere uno de los conjuntos sta, consulte directamente el otro conjunto disjunto (((1 << 20) -1) ^ sta), y luego Solo ve al máximo.

#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const int maxn=1e6+10;
int dp[1<<20];
char s[maxn];
int main()
{
    cin>>s+1;
    int n=strlen(s+1);
    for (int i=1;i<=n;i++)
    {
        int sum=0;
        for (int j=i;j<=n;j++)
        {
            if(sum&(1<<(s[j]-'a')))
            break;
            sum|=(1<<(s[j]-'a'));
            dp[sum]=j-i+1;
        }
    }
    for(int i=0;i<(1<<20);i++)
    {
        for (int j=0;j<20;j++)
        {
            if (i&(1<<j))
            dp[i]=max(dp[i],dp[i^(1<<j)]);
        }
    }
    int ans=0;
    int sum=(1<<20)-1;
    for (int i=0;i<(1<<20);i++)
    {
        ans=max(ans,dp[i]+dp[sum^i]);
    }
    cout<<ans;
    return 0;
}
12 artículos originales publicados · Me gusta1 · Visitas 327

Supongo que te gusta

Origin blog.csdn.net/qq_41818939/article/details/104752657
Recomendado
Clasificación