【题 解】 CF535D Tavas y Malekas

Comprensión lectora

Explicación

La longitud de la cadena de texto dada nnn y una cadena de patrónsss , y dado que la cadena de patrón aparece en ciertas posiciones en la cadena de texto (no necesariamente solo en estas posiciones), encuentre el número de cadenas de texto posibles.

análisis

Primero ingrese la posibilidad de que el esquema sea 0 (es decir, ilegal), por lo que primero consideramos el juicio ilegal.

Es obvio que cuando ssLa posición final de s es mayor quennCuando es n , se puede juzgar directamente como ilegal.

Entonces, cuando las dos cadenas de patrones se superponen, si la parte superpuesta no coincide, obviamente no hay solución. (El método de determinación específico se discutirá más adelante)

Si hay una solución, solo necesitamos contar cuántas posiciones en la cadena de texto no están cubiertas por la cadena de patrón, que se registra como cnt cntc n t , entonces la respuesta es2 6 cnt 26 ^ {cnt}2 6c n t


Específicamente, considere cómo determinar si la parte superpuesta coincide. Obviamente, la parte superpuesta es la superposición de un sufijo y un prefijo de la cadena del patrón, por lo que solo necesitamos juzgar si el sufijo y el prefijo en la posición actual coinciden. Y este juicio se puede realizar de dos formas: KMP KMPK M P y hash de cadena.

KMP

Encontramos el problema y KMP KMPSiguiente siguienteen el algoritmo K M PLa definición de la matriz n e x t es similar, por lo que podemos pensar en: comenzar desde el final de la cadena del patrón y seguir saltando acontinuación.n e x t puntero, el prefijo de la posición pasada en el camino debe ser igual al sufijo (piensesiguiente siguienteEl significado de la matriz n e x t ). Entonces solo necesitamos marcar estas posiciones, solo cuando estas posiciones se superponen, el prefijo y el sufijo pueden ser iguales.

Hash de cadena

Cuando se trata de la comparación de cadenas, definitivamente puedes pensar en hashes de cadenas. Primero podemos preprocesar el valor hash de la cadena de patrón y luego juzgar si el prefijo y el sufijo son iguales cuando se superponen.

Código

Hay un agujero en los datos, debemos juzgar m = 0 m = 0metro=0 situación.

KMP

#include <bits/stdc++.h>
#define ll long long
#define P 1000000007
#define MAX 1000005
using namespace std;

ll qpow(ll a, ll n){
    
    
    ll res = 1;
    while(n){
    
    
        if(n&1) res = res*a % P;
        a = a*a%P;
        n >>= 1;
    }
    return res;
}

char s[MAX];
int n, m, len, Next[MAX], mark[MAX], p[MAX];

void init(){
    
    
    int j = 0;
    len = strlen(s+1);
    for(int i = 2; i <= len; i++){
    
    
        while(j && s[j+1] != s[i]){
    
    
            j = Next[j];
        }
        if(s[j+1] == s[i]) j++;
        Next[i] = j;
    }
    for(int i = len; i; i = Next[i]){
    
    
        mark[i] = 1;
    }
}

int main()
{
    
    
    cin >> n >> m;
    scanf("%s", s+1);
    init();
    for(int i = 1; i <= m; i++){
    
    
        scanf("%d", &p[i]);
    }
    if(!m){
    
    
        cout << qpow(26, n) << endl;
        return 0;
    }
    for(int i = 1; i <= m; i++){
    
    
        if(p[i]+len-1 > n){
    
    
            puts("0");
            return 0;
        }
        if(i > 1 && p[i-1]+len > p[i]){
    
    
            int x = p[i-1]+len-p[i];
            if(!mark[x]){
    
    
                puts("0");
                return 0;
            }
        }
    }
    int cnt = p[1]-1;
    for(int i = 1; i < m; i++){
    
    
        if(p[i]+len < p[i+1]){
    
    
            cnt += p[i+1]-p[i]-len;
        }
    }
    cnt += n-p[m]-len+1;
    cout << qpow(26, cnt) << endl;
    
    return 0;
}

Hash de cadena

#include <bits/stdc++.h>
#define ll long long
#define P 1000000007
#define MAX 1000005
using namespace std;

ll qpow(ll a, ll n){
    
    
    ll res = 1;
    while(n){
    
    
        if(n&1) res = res*a % P;
        a = a*a%P;
        n >>= 1;
    }
    return res;
}

const ll b1 = 99979, b2 = 100007;
const ll p = 1e9+7, q = 1e9+9;
ll p1[MAX], sum1[MAX], p2[MAX], sum2[MAX];
char s[MAX];
int n, m, len, a[MAX];

void init(){
    
    
    len = strlen(s+1);
    p1[0] = 1;
    for(int i = 1; i <= len; i++){
    
    
    	p1[i] = p1[i-1]*b1%p;
    }
    p2[0] = 1;
    for(int i = 1; i <= len; i++){
    
    
    	p2[i] = p2[i-1]*b2%q;
    }
    sum1[0] = 0;
    for(int i = 1; i <= len; i++){
    
    
        sum1[i] = (sum1[i-1]*b1%p+s[i]-'a')%p;
    }
    sum2[0] = 0;
    for(int i = 1; i <= len; i++){
    
    
        sum2[i] = (sum2[i-1]*b2%q+s[i]-'a')%q;
    }
}

int main()
{
    
    
    cin >> n >> m;
    scanf("%s", s+1);
    init();
    for(int i = 1; i <= m; i++){
    
    
        scanf("%d", &a[i]);
    }
    if(!m){
    
    
        cout << qpow(26, n) << endl;
        return 0;
    }
    for(int i = 1; i <= m; i++){
    
    
        if(a[i]+len-1 > n){
    
    
            puts("0");
            return 0;
        }
        if(i > 1 && a[i-1]+len > a[i]){
    
    
            int x = a[i-1]+len-a[i];
            if(sum1[x]!=(sum1[len]%p-sum1[len-x]*p1[x]%p+p)%p || sum2[x]!=(sum2[len]-sum2[len-x]*p2[x]%q+q)%q){
    
    
                puts("0");
                return 0;
            }
        }
    }
    
    int cnt = a[1]-1;
    for(int i = 1; i < m; i++){
    
    
        if(a[i]+len < a[i+1]){
    
    
            cnt += a[i+1]-a[i]-len;
        }
    }
    cnt += n-a[m]-len+1;
    cout << qpow(26, cnt) << endl;
    
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_30115697/article/details/89788049
Recomendado
Clasificación