Coincidencia de soportes | Procesamiento de cadenas

10. Coincidencia de soportes

Los grados 10 hora de apertura Jueves, 10 de septiembre de 2020 12:00
descuento 0,8 Tiempo de descuento Jueves, 17 de septiembre de 2020 09:00
Se permite la presentación tardía No Hora de cierre Sábado, 10 de octubre de 2020 23:00

Descripción

La secuencia de corchetes es una secuencia no vacía compuesta por el corchete izquierdo "(" y el corchete derecho ")". Es fácil determinar la validez de una secuencia de paréntesis. Por ejemplo, "()", "(()) ()", "(() ())", "(() (()))", "() () ()" son todos legales, mientras que " ) "," ("," (() "," (())) ("son todos ilegales.

Dadas n secuencias de corchetes, emparejarlas en pares y preguntar cuántos pares de secuencias de corchetes legales se pueden formar. (Cada secuencia de corchetes solo puede aparecer en un par)

Entrada

Ingrese el número entero n en la primera línea para indicar que hay n secuencias de corchetes, y en las siguientes n líneas, ingrese n secuencias de corchetes.

Salida

Genere un número entero que represente el mayor número de pares de secuencias de corchetes legales.

Insinuación

El primer conjunto de casos de uso puede formar dos pares de secuencias de corchetes legales, a saber, "(() ())" y "()".


1. Operación simplificada de la secuencia de brackets

       Esta pregunta es un problema clásico de coincidencia de corchetes. Primero veamos una sola cadena de corchetes. ¿Cómo juzgamos que coincide? Tome la cadena de corchetes ((() ())) como ejemplo, ¡parece que coincide de un vistazo! Entonces, ¿cómo pensamos en él de manera procedimental?
       No es tan bueno como esto: preparamos una pila de contenedores con un solo extremo abierto , y se estipula que solo podemos poner la parte superior de este contenedor en orden, o quitar la parte superior . Como aprenderá más adelante, este tipo de contenedor se llama pila, que es una estructura de datos muy común. El siguiente es un diagrama esquemático del funcionamiento básico de la pila, solo entienda este modelo.

Java Edition-Data Structure-Stack | El programa Road of Xiaobai

 

       A continuación, necesitamos simplificar la cadena de corchetes a través del contenedor anterior, de modo que la cadena que obtengamos después de simplificar, la conclusión de si coincide sea la misma que la cadena original. Atraviese cada elemento t en la cadena de corchetes por turno, y las operaciones específicas para cada elemento son las siguientes (si no comprende este proceso, pruébelo usted mismo manualmente):

  • Si el elemento superior de la pila de contenedores (la pila no está vacía) coincide con t: retire el elemento superior de la pila;
  • Si la pila de contenedores está vacía o el elemento superior de la pila de contenedores no coincide t: coloque el elemento t en la parte superior de la pila

       Una vez que se completa el recorrido, nuestra cadena de corchetes simplificada está en el contenedor . Si la pila de contenedores está vacía, la cadena de soporte en sí coincide, de lo contrario, no debe coincidir .


 2. Ideas para esta pregunta       

    Echemos un vistazo a los requisitos de esta pregunta nuevamente: Tenemos que juzgar si las dos cadenas de corchetes s1 y s2 pueden formar una cadena de corchetes coincidente. Entonces debería haber dos situaciones:

  • s1 y s2 son paréntesis coincidentes y deben coincidir.
  • Tanto s1 como s2 no son cadenas coincidentes, pero sus cadenas simplificadas pueden coincidir entre sí.

       Aquí nos enfocamos en el segundo caso, después de la coincidencia si se simplifica, entonces dos cadenas deben simplificarse uniformemente (solo paréntesis izquierdo / paréntesis derecho uno), y simplificar dos cadenas el mismo número de elementos especies contrarias .

Por ejemplo, s1:) (())) se puede simplificar a))
Por ejemplo, s2: (() (se puede simplificar a ((Las
dos cadenas simplificadas se pueden combinar, por lo que la cadena original también se puede combinar.


        Entonces, según el resumen anterior, resolvimos el algoritmo de este problema:
        para las n cadenas de entrada, las simplificamos una por una y registramos los resultados simplificados. Si está vacío, registre la cantidad de cadenas coincidentes; de lo contrario, regístrelas como varios paréntesis izquierdos / varios paréntesis derechos y registre los números en las matrices izquierda y derecha. (Si hay un paréntesis izquierdo y un paréntesis derecho después de la simplificación, no debe coincidir con ninguna cadena, simplemente ignórelo) La

        pregunta requiere que cada cadena solo pueda coincidir una vez, y la izquierda [i] registra la longitud de la i simplificada El número de cadenas entre paréntesis de la izquierda es el mismo para la matriz de la derecha. Luego, nuestro número total final de coincidencias debe calcularse de la siguiente manera: las cadenas de cálculo que coinciden por sí mismas se pueden combinar en el grupo calc / 2 como máximo; atraviesa la matriz izquierda y toma min (izquierda [i], derecha [i]).


3. Implementación del código

       Después de comprender las ideas anteriores, escribir código es más fácil. Puede que sea la primera vez que me pongo en contacto con la pila, y no sé cómo implementar este modelo mediante programación. El siguiente código se implementa a través de una matriz unidimensional y subíndices móviles . Esta es una forma de código c para implementar la pila. De hecho, es incluso más fácil si es C ++. Hay una pila empaquetada en la biblioteca de pila de C ++. Podemos definirla directamente como tipos de datos básicos (como int), y luego usarla directamente. Sin embargo, en este tema de música, solo se permite entregar el código c. Lo cambiaré ac y lo pegaré aquí para emmmm ... El código completo es el siguiente:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 100050


/* 分别记录化简之后,全为左括号/右括号的串的个数,下标代表括号个数
 * 如:left[3]代表"((("有多少个,right[2]代表"))"有多少个 */
long long left[MAX_LEN] = {0}, right[MAX_LEN] = {0};
long long calc = 0;  //记录化简之和位空串的个数(该串化简前本身就是合法的)

int match(char c1, char c2) {
    if(c1 == '(' && c2 == ')')
        return 1;
    else
        return 0;
}

/* 处理字符串s,将其化为最简形式
 * 并将最简形式记录在left/right数组中 */
void dealStr(char s[]) {
    /* 利用栈依次考虑每一个字符
     * 最终将其最简形式留在栈内 */
    char stack[MAX_LEN];
    int top_index = -1;  //指向栈顶元素下标
    for (int i = 0; i < strlen(s); i++) {
        //当栈非空 且 栈顶与待加入元素相匹配时
        if (top_index != -1 && match(stack[top_index], s[i]))
            top_index--;  //出栈
        else
            stack[++top_index] = s[i];  //入栈
    }
    /* 处理其最简形式,进行记录 */
    //最简形式为空,本身就是匹配的
    if (top_index == -1) {
        calc++;
        return;
    }

    char c = stack[top_index];
    int count = top_index + 1; //记录下化简完后的栈内剩余元素

    while (top_index >= 0) {
        if (stack[top_index] != c)  //栈内剩余字符串不是同号的
            return;
        top_index--;
    }

    if (c == '(')
        left[count]++;
    else
        right[count]++;
}


int main() {
    int n;
    char str[MAX_LEN];
    scanf("%d\n", &n);  //一定记得吸去换行符

    /* 依次读入初始字符串并进行处理 */
    for (int i = 0; i < n; i++) {
        scanf("%s", str);
        dealStr(str);
    }

    //本身就是匹配的字符串,两两匹配
    long long ans = calc / 2;
    for (int i = 0; i < MAX_LEN; i++) {
        ans += left[i] < right[i] ? left[i] : right[i];
    }

    printf("%lld\n", ans);
}


Bienvenido a prestar atención a la cuenta pública personal "  Programación de ala de pollo" , aquí hay un granjero de código serio y de buen comportamiento.

---- Sea el blogger más educado y el programador más sólido ----

Trate de escribir cada artículo con cuidado y, por lo general, resuma las notas en actualizaciones automáticas ~

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_43787043/article/details/108518190
Recomendado
Clasificación