Aplicación simple del árbol Trie y conjunto de búsqueda (AcWing)

arbol de tria

Trie tree, también llamado "árbol de diccionario". Como su nombre indica, es una estructura de árbol. Es una estructura de datos que se ocupa específicamente de la coincidencia de cadenas y se utiliza para resolver el problema de encontrar rápidamente una determinada cadena en un conjunto de cadenas.

 Al final de cada palabra se debe marcar, contar el número

Ahora simule el ejemplo anterior

 Trie string estadísticas

Código CA:

#include<iostream>
using namespace std;
const int N=100010;
int son[N][26],cnt[N],idx,m;
char str[N];

void insert(char* str)
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int u=str[i]-'a';//映射
        if(!son[p][u]) son[p][u]=++idx;
        p=son[p][u];
    }
    cnt[p]++;//计数
}

int find(char* str)
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int u=str[i]-'a';
        if(!son[p][u]) return 0;
        p=son[p][u];
    }
    return cnt[p];
}

int main(void)
{
    scanf("%d",&m);
    while(m--)
    {
        char op[5];
        scanf("%s %s",op,str);
        if(op[0]=='I')
        {
            insert(str);
        }else
        {
            printf("%d\n",find(str));
        }
    }
    return 0;
}

 y buscar

Y busque, en algunos problemas de aplicaciones de colección con N elementos, generalmente dejamos que cada elemento forme una colección de un solo elemento al principio, y luego fusionamos las colecciones de elementos que pertenecen al mismo grupo en un cierto orden, durante el cual Iteramos sobre qué conjunto se encuentra un elemento. Este tipo de problema ha aparecido repetidamente en concursos internacionales y nacionales de informática en los últimos años. Su característica es que no parece complicado, pero la cantidad de datos es enorme, si se describe mediante una estructura de datos normal, a menudo es demasiado grande en el espacio y la computadora no puede soportarlo, incluso si apenas pasa en el espacio, el La complejidad del tiempo de operación es extremadamente alta Alta, es simplemente imposible calcular los resultados requeridos para las preguntas de la prueba dentro del tiempo de ejecución especificado en la competencia (1 a 3 segundos), y solo puede ser descrito por búsqueda conjunta.

El conjunto de búsqueda de unión es una estructura de datos de tipo árbol, que se utiliza para tratar los problemas de combinación y consulta de algunos conjuntos disjuntos (conjuntos disjuntos). A menudo se expresa como un bosque en uso.

Primero cree tres colecciones. Como se puede ver en la figura, cada punto puede encontrar su propio nodo ancestro paso a paso. Si los nodos ancestros son los mismos, entonces están en la misma colección, pero la eficiencia es muy ineficiente si cada búsqueda se hace uno por uno Sí, entonces podemos usar la compresión de ruta , es decir, después de recorrer una colección, apuntamos todos los nodos de esta colección a los nodos antepasados, entonces la complejidad de tiempo de la próxima búsqueda es O (1) , lo que mejora en gran medida la eficiencia de búsqueda 

Esta operación se puede implementar en un proceso recursivo.

int find(int x)
{
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}

Como se mencionó antes, para juzgar si uno pertenece al mismo conjunto, juzgue si sus nodos ancestros son los mismos. Si son iguales, estos dos nodos están en el mismo conjunto, luego fusione los dos nodos de AB, entonces podemos hacer el nodo A El nodo ancestro se establece en el nodo ancestro de B, luego las dos colecciones de AB se fusionan

combinar colección

Código CA: 

#include<iostream>
using namespace std;
const int N=100010;
int p[N],n,m;

int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

int main(void)
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) p[i]=i;
    while(m--)
    {
        char op[5];
        int a,b;
        scanf("%s",op);
        if(op[0]=='M')
        {
        scanf("%d %d",&a,&b); 
        p[find(a)]=p[find(b)];
        }
        else
        {
            scanf("%d %d",&a,&b);
            if(p[find(a)]==p[find(b)]) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

El número de puntos medios en bloques conectados.

 Los bloques conectados en esta pregunta se pueden considerar como elementos en un conjunto. Los bloques conectados conectados están en un conjunto. La diferencia entre esta pregunta y la pregunta anterior es que hay un tamaño adicional. También necesitamos mantener una matriz de tamaño para Registre el número de elementos en la colección actual. El método de registro es agregar el tamaño de la colección A directamente a la colección B al fusionar dos colecciones.

código de CA

#include<iostream>
using namespace std;
const int N=100010;
int p[N],sz[N],n,m,a,b;

int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

int main(void)
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) 
    {
    p[i]=i;
    sz[i]=1;
    }
    while(m--)
    {
        char op[5];
        scanf("%s",op);
        if(op[0]=='C')
        {
            scanf("%d %d",&a,&b);
            if(find(a)==find(b)) continue;
            sz[find(a)]+=sz[find(b)];
            p[find(b)]=p[find(a)];
        }else if(op[1]=='1')
        {
            scanf("%d %d",&a,&b);
            if(find(a)==find(b))puts("Yes");
            else puts("No");
        }else 
        {
            scanf("%d",&a);
            printf("%d\n", sz[find(a)]);
        }
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/AkieMo/article/details/128508882
Recomendado
Clasificación