[C ++] entrenamiento de verano henuACM Día 11 KMP

Antes de escribir la solución, permítanme publicar un blog sobre KMP https://blog.csdn.net/v_july_v/article/details/7041827
. En serio, ayer el senior dijo que el KMP de hoy sería un poco difícil, pero sígalo. Puede entender. Efectivamente, jugué QQ en el medio del juego, pero no sucedió == pasé una tarde para entender, y finalmente entendí tres o cuatro, pero para las preguntas que no son de plantilla, todavía necesito entender mejor KMP una y otra vez.

Un sujeto Oulipo

El autor francés Georges Perec (1936-1982) escribió una vez un libro, La desaparición, sin la letra "e". Fue miembro del grupo Oulipo. Una cita del libro:
Todo parecía normal, pero todo decía estar mal. Todo fue normal, al principio, luego surgió lo inhumano, enloquecedor. Le hubiera gustado saber dónde se articulaba la asociación que lo unía a la novela: en su alfombra, asaltando en todo momento su imaginación, la intuición de un tabú, la visión de un mal oscuro, de algo vacío. , de un tácito: la visión, la anticipación de un olvido controlando todo, donde la razón fue abolida: todo parecía normal pero ...
Perec probablemente habría obtenido una puntuación alta (o más bien, baja) en el siguiente concurso. Se pide a las personas que escriban un texto quizás incluso significativo sobre algún tema con el menor número posible de apariciones de una "palabra" determinada. Nuestra tarea es proporcionar al jurado un programa que cuente estas ocurrencias, con el fin de obtener una clasificación de los competidores. Estos competidores suelen escribir textos muy largos con un significado sin sentido; una secuencia de 500.000 'T's consecutivas no es inusual. Y nunca usan espacios.
Por tanto, queremos averiguar rápidamente con qué frecuencia aparece una palabra, es decir, una cadena determinada, en un texto. Más formalmente: dado el alfabeto {'A', 'B', 'C',…, 'Z'} y dos cadenas finitas sobre ese alfabeto, una palabra W y un texto T, cuente el número de apariciones de W en T Todos los caracteres consecutivos de W deben coincidir exactamente con los caracteres consecutivos de T. Las ocurrencias pueden superponerse.

Entrada

La primera línea del archivo de entrada contiene un solo número: el número de casos de prueba a seguir. Cada caso de prueba tiene el siguiente formato:

  • Una línea con la palabra W, una cadena sobre {'A', 'B', 'C',…, 'Z'}, con 1 ≤ | W | ≤ 10,000 (aquí | W | denota la longitud de la cuerda W).
  • Una línea con el texto T, una cadena sobre {'A', 'B', 'C',…, 'Z'}, con | W | ≤ | T | ≤ 1.000.000.

Salida

Para cada caso de prueba en el archivo de entrada, la salida debe contener un solo número, en una sola línea: el número de apariciones de la palabra W en el texto T.

Entrada de muestra

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Salida de muestra

1
3
0

El significado de la pregunta: da una cadena y luego una cadena de destino, cuántas veces aparece este destino en la cadena larga

Idea: Entiendo que el llamado KMP es optimizar la posición del próximo partido después de que cada partido falla sobre la base del partido violento. El partido violento se mueve un lugar a la derecha cada vez, pero esto perderá mucho tiempo en emparejar Apunta más allá. En KMP, se introduce una siguiente matriz y la siguiente matriz se obtiene del mismo prefijo y sufijo de la cadena de destino. Cuando hay una discrepancia, el número de bits que la cadena de patrón se mueve hacia la derecha es: la posición del carácter no coincidente - el siguiente valor correspondiente al carácter no coincidente .

Encuentra la plantilla de la siguiente matriz.
A veces, k se inicializa a 0 y j es 1

void getnext(int len) 
{ 
    int j, k; 
    j = 0; k = -1; //初始化值为-1且下标从0开始
    next[0] = -1; 
    while(j < len) 
{ 
    if(k == -1 || b[j] == b[k]) 
    { 
        j++; k++; 
        next[j] = k; 
    } 
    else k = next[k]; } } 

Plantilla KMP

int kmp(int len1, int len2) 
{ 
    int i, j; 
    int cnt = 0; 
    i = 0; j = 0; 
    getnext(len2); //得到目标串的next数组 
    while(i < len1) 
    { 
        if(j == -1 || a[i] == b[j]) 
        { 
            i++; j++; 
        } 
        else j = next[j]; 
        if(j == len2) cnt++; //记录目标串出现的次数 
    } 
    return cnt; 
} 

Código de CA completo

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxx = 1e6+10;
char s1[maxx],s2[maxx];

int nextt[maxx];

void getnext(int len)
{
    int j,k;
    j=0;k=-1;
    nextt[0] = -1;
    while(j<len)
    {
        if(k == -1 || s2[k] == s2[j]){
            ++k;++j;
            nextt[j] = k;
        }
        else{k = nextt[k];}
    }
}

int kmp(int len1,int len2)
{
    int i=0;int j=0;int ans=0;
    getnext(len2);
    while(i<len1)
    {
        if(j == -1 || s1[i] == s2[j])
        {
            ++i;++j;
        }
        else{j = nextt[j];}
        if(j==len2){ans++;}
    }
    return ans;
}

int main()
{
    int n;
    scanf("%d",&n);
    //cin>>n;
    while(n--)
    {
        scanf("%s%s",s2,s1);
        //cin>>s2>>s1;
        int len1 = strlen(s1);
        int len2 = strlen(s2);
        printf("%d\n",kmp(len1,len2));
        //cout<<kmp(len1,len2)<<endl;
    }
    return 0;
}

Nota:

  1. Cin cout se agotará, y se necesitan scanf y printf. Sin embargo, la entrada y salida del lenguaje C no pueden operar directamente en la clase de cadena. El método se aprenderá más adelante. Aquí, reemplazaremos temporalmente cadena con char.

  2. Use strlen () para
    encontrar la longitud del tipo char y str.length () para encontrar la longitud del tipo de cadena

  3. Next puede informar un error en vj y cambiar a nextt.

Supongo que te gusta

Origin blog.csdn.net/qq_44899247/article/details/97276323
Recomendado
Clasificación