【POJ 3461】 Oulipo (KMP)

Oulipo

Límite de tiempo: 1000MS Límite de memoria: 65536K

Descripción

El autor francés Georges Perec (1936-1982) escribió una vez un libro, La disparition, 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 apareció 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 la menor cantidad posible de apariciones de una "palabra" determinada. Nuestra tarea es proporcionar al jurado un programa que cuente estas ocurrencias, con el fin de obtener un ranking 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.

Así que 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 cadena 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

Idea principal: Ingrese los datos del grupo T. Cada conjunto de datos tiene dos cadenas y genera el número de veces que la primera cadena aparece en la segunda cadena. Por ejemplo, AZA tiene 2 veces en AZAZA y tres veces en AZAZAZA.

Análisis: problema típico de KMP. Coincidencia de un solo patrón.
Si no comprende el algoritmo KMP, consulte:
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"

using namespace std;

const int maxn = 1e4+5;

int next[maxn];

char str1[maxn];
char str2[1000005];

/*/////简单但是会超时 
void MakeNext( char *p ){
    int i,k;//Q记录字符串下标 k是最大前后相同缀长度
    int m = strlen(p);//字符串长度
    next[0] = -1;//第一个字符串的前后缀长度为0
    for( i=1 , k=0 ; i<m ; i++ ){
        while( k>0 && p[i] != p[k] ){
   
   //求出p[0]-->p[i]的最大前后缀长度 
            k = next[k-1];
        } 
        if( p[i] == p[k] ){
            k++;
        }
        next[i] = k;
    } 
} 
*/

void MakeNext( char *str ){
    int n = strlen(str);
    int i = 0, j = -1;
    next[0] = -1;
    while( i < n ){
        if( j == -1 || str[i] == str[j] )
            next[++i] = ++j;
        else
            j = next[j];
    }
}

int kmp( char *p,char *str ){
    int n = strlen(p);
    int m = strlen(str);
    int i = 0;
    int j = 0;
    int cnt = 0;
    while( i<m && j<n ){
        if( str[i] == p[j] || j == -1 ){
            i++;
            j++;
        }
        else{
            j = next[j];
        }
        if( j == n ){
            cnt++;
            j = next[j];
        }
    }
    return cnt;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s",str1);
        scanf("%s",str2);
        MakeNext( str1 );
        int ans = kmp( str1,str2 );
        printf("%d\n",ans);
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/thesprit/article/details/52152465
Recomendado
Clasificación