Compruebe si las subsecuencias formadas por los caracteres dados son las mismas para las consultas Q

Dada una array arr[] de N strings y Q consultas donde cada una de las consultas contiene algunos caracteres, la tarea es verificar si para cada consulta las subsecuencias de todas las strings solo están compuestas por todas las ocurrencias de los caracteres de esa consulta son iguales o no. 

Una subsecuencia es una secuencia que se puede derivar de la secuencia dada eliminando algunos o ningún elemento sin cambiar el orden de los elementos restantes. 

Ejemplos:

Entrada: arr[] = {“accbad”, “abcacd”, “cacbda”}, consultas[] = {{‘a’}, {‘a’, ‘b’}, {‘a’, ‘d’} , {‘b’, ‘c’, ‘d’}, {‘a’, ‘b’, ‘d’} Salida:
Verdadero 
Verdadero
Falso
Verdadero
Falso
Falso
Explicación
: Todas las strings generan la subsecuencia «aa» usando solo el carácter ‘a’.
Todas las strings generan la subsecuencia «aba» usando solo los caracteres ‘a’ y ‘b’.
arr[1] y arr[2] generan la subsecuencia “aad”, pero arr[3] genera la subsecuencia “ada” usando solo los caracteres ‘a’ y ‘d’, y dado que las subsecuencias no coinciden, se imprime falso.
Todas las strings generan la subsecuencia «bd» usando solo los caracteres ‘b’ y ‘d’
arr[1] y arr[3] generan la subsecuencia «ccbd», pero arr[2] genera la subsecuencia «bccd» usando solo los caracteres ‘b’, ‘c’ y ‘d’, por lo que imprime ‘False’.
arr[1] y arr[2] generan la subsecuencia «abad», pero arr[3] genera la subsecuencia «abda» usando solo los caracteres ‘a’, ‘b’ y ‘d’

Entrada: arr[] = {“adacb”, “aacbd”}, consultas[] = {{‘a’, ‘b’, ‘c’}} Salida:
Verdadero .
Explicación: Las subsecuencias son ‘aacb’ para ambas strings

 

Enfoque ingenuo: para cada consulta, genere las subsecuencias que contienen todas las ocurrencias de todos los caracteres de esa consulta y verifique si son iguales o no.

Complejidad temporal: O(Q * N * M), donde M es la longitud media de cada string.
Espacio Auxiliar: O(1)

Enfoque eficiente utilizando la memorización: este problema se puede resolver de manera eficiente en función de la siguiente idea:

Si las posiciones relativas de todos los caracteres de una consulta son las mismas en todas las strings, la subsecuencia es común en todas ellas.

Las posiciones relativas de cualquier carácter (por ejemplo, el carácter ch ), se pueden averiguar encontrando las frecuencias de todos los caracteres de una consulta hasta el índice de ch . Si son iguales, entonces su posición relativa también es la misma.

Siga los pasos mencionados a continuación para implementar la idea:

  • Cree una array tridimensional (por ejemplo, elementos [] ) para almacenar la frecuencia de cada carácter de las strings hasta cada índice.
  • Atraviesa todas las cuerdas y encuentra la frecuencia y guárdalas
  • Ahora verifique las posiciones relativas de los caracteres de una consulta.
  • Para implementar esto de manera eficiente, itere a través de la array de strings, compare las strings adyacentes y haga lo siguiente:
    • Encuentre la posición relativa de cada carácter con respecto a todos los demás caracteres del alfabeto inglés (la posición relativa se comprueba comprobando las frecuencias de todos los demás caracteres hasta ese índice).
    • Si no son los mismos para un carácter (por ejemplo, ch ) en dos strings, agregue los caracteres que causan la falta de coincidencia en un conjunto . (la discrepancia significa que los conteos de frecuencia no son los mismos)
    • Compruebe si las discrepancias encontradas son las mismas que los caracteres de la consulta.
    • Si es así, las subsecuencias formadas no son las mismas. Así que devuelve falso .
  • Una vez que finaliza la iteración y no se devuelve un «falso», las subsecuencias formadas son las mismas.

Siga la ilustración a continuación para una mejor comprensión.

Ilustración:

Diga arr[] = {“adacb”, “aacbd”}, consultas[] = {{‘a’, ‘b’, ‘c’}}

Las frecuencias de todos los caracteres para arr[0] y arr[1] se muestran a continuación

arr[0] = 

 

‘a’

‘d’ ‘a’ ‘C’ ‘b’
a 1 1 2 2 2
b 0 0 0 0 1
C 0 0 0 1 1
d 0 1 1 1 1

array[1] = 

 

‘a’

‘a’ ‘C’ ‘b’ ‘d’
a 1 2 2 2 2
b 0 0 0 1 1
C 0 0 1 1 1
d 0 0 0 0 1

Para ‘a’:
        => Las posiciones relativas de la segunda ‘a’ no son las mismas.
        => En la primera string hay una ‘d’ adicional antes de la segunda ‘a’.
        => Entonces el conjunto de desajustes es { ‘d’ } .

Para ‘b’:
        => Las posiciones relativas de ‘b’ no son las mismas.
        => En la primera string hay una ‘d’ adicional antes.
        => Entonces el conjunto de desajustes es { ‘d’ } .

Para ‘c’:
        => Las posiciones relativas de ‘c’ no son las mismas.
        => En la primera string hay una ‘d’ adicional antes.
        => Entonces el conjunto de desajustes es { ‘d’ } .

Ahora ningún conjunto de discrepancias contiene el mismo carácter que los presentes en la consulta. Entonces la subsecuencia formada es la misma para las strings.

A continuación se muestra la implementación del enfoque anterior.

Java

// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
public class SubsequenceQueries {
 
    // Function to check if
    // the subsequences formed are the same
    public static ArrayList<Boolean>
    isPossible(int N, ArrayList<String> arr, int Q,
               String queries[])
    {
        // For 26 letters
        final int numElements = 26;
 
        // Generate prefix sums (for each letter)
        // for each string
        ArrayList<int[][]> elements
            = new ArrayList<>();
        for (int i = 0; i < N; i++) {
 
            // Create a new prefix sum array
            // and add it to the array list
            elements.add(new int[arr.get(i).length()]
                                [numElements]);
            int[][] tmp = elements.get(i);
 
            // Build the prefix sum
            // at each position in the string
            for (int j = 0; j < arr.get(i).length();
                 j++) {
                for (int k = 0; k < numElements;
                     k++) {
                    if (j != 0)
                        tmp[j][k] = tmp[j - 1][k];
                }
 
                // ASCII to int conversion
                // for lowercase letters
                tmp[j][arr.get(i).charAt(j) - 97]++;
            }
        }
 
        // Generate the set of characters
        // which are necessary to remove.
        // Each mapping is the set
        // corresponding of characters
        // which need to be removed.
        // for each letter in order for a
        // subsequence to be generated.
        HashMap<Integer, Set<Integer> > requiredRemovals
            = new HashMap<>();
        for (int i = 0; i < numElements; i++)
            requiredRemovals.put(i, new HashSet<Integer>());
 
        // Iterate over all the characters
        // (in the alphabet in this case)
        for (int i = 0; i < numElements; i++) {
 
            // For each character,
            // go through all M strings
            // to generate prefix sums
            for (int j = 1; j < N; j++) {
 
                // String a stores
                // the previous string (j-1)
                // string b stores
                // the current string (j)
                String a = arr.get(j - 1);
                String b = arr.get(j);
 
                // Store the prefix sums
                // for strings a and b
                int[][] elements1
                    = elements.get(j - 1);
                int[][] elements2
                    = elements.get(j);
 
                int p1 = 0;
                int p2 = 0;
 
                // Check if the lengths of characters
                // differ; if they do, then
                // no valid subsequence
                // with that character can be generated.
                // So for all other letters,
                // add that character to its Set.
                // Otherwise, check the count
                // of each character
                // at every position where
                // letter i appears in both strings
                if (elements1[a.length() - 1][i]
                    != elements2[b.length() - 1][i]) {
                    for (int key :
                         requiredRemovals.keySet())
                        requiredRemovals.get(key).add(i);
                }
                else {
                    // Iterate through both strings
                    // using p1 for all characters
                    // in the first string
                    // and p2 for all characters
                    // in the second string
                    while (p1 < a.length()
                           && p2 < b.length()) {
 
                        // Skip to the next occurrence of
                        // character i in string a
                        while (p1 < a.length()
                               && a.charAt(p1)
                                          - 97
                                      != i) {
                            p1++;
                        }
 
                        // Skip to the next occurrence of
                        // character i in string b
                        while (p2 < b.length()
                               && b.charAt(p2)
                                          - 97
                                      != i) {
                            p2++;
                        }
 
                        // Compare the count of each
                        // character to check if they match
                        // in both strings
                        if (p1 < a.length()
                            && p2 < b.length()) {
 
                            // Iterate over
                            // their prefix sums
                            for (int k = 0;
                                 k < numElements;
                                 k++) {
                                if (elements1[p1][k]
                                    != elements2[p2][k])
                                    requiredRemovals.get(i)
                                        .add(k);
                            }
                        }
                        p1++;
                        p2++;
                    }
                }
            }
        }
 
        ArrayList<Boolean> res
            = new ArrayList<Boolean>();
 
        // Read in Q queries
        for (int i = 0; i < Q; i++) {
 
            // st = new StringTokenizer(br.readLine());
            // String q = st.nextToken();
            Set<Integer> union
                = new HashSet<Integer>();
 
            // generate a combined set of all characters
            // which must be removed for a valid subsequence
            // to be created with the query string
            for (char c : queries[i].toCharArray())
                union.addAll(requiredRemovals.get(c - 97));
            boolean ans = true;
 
            // if there are any contradictions in the query,
            // then the answer will be false
            for (char c : queries[i].toCharArray()) {
                if (union.contains(c - 97))
                    ans = false;
            }
 
            res.add(ans);
        }
        return res;
    }
 
    // Driver code
    public static void main(String[] args)
        throws IOException
    {
        int N = 3;
        ArrayList<String> arr
            = new ArrayList<String>();
        arr.add("accbad");
        arr.add("abcacd");
        arr.add("cacbda");
        int Q = 6;
        String queries[]
            = new String[6];
        queries[0] = "a";
        queries[1] = "ab";
        queries[2] = "ad";
        queries[3] = "bd";
        queries[4] = "bcd";
        queries[5] = "abd";
 
        // Function call
        ArrayList<Boolean> ans
            = isPossible(N, arr, Q, queries);
        for (boolean val : ans)
            System.out.println(val);
    }
}

C#

// C# program to implement above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
    // For 26 letters
    readonly public static int numElements = 26;
 
    // Function to check if
    // the subsequences formed are the same
    public static List<bool> isPossible(int N, List<String> arr, int Q, String[] queries)
    {
 
        // Generate prefix sums (for each letter)
        // for each string
        List<int[, ]> elements = new List<int[, ]>();
        for (int i = 0 ; i < N ; i++) {
 
            // Create a new prefix sum array
            // and add it to the array list
            elements.Add(new int[arr[i].Length, numElements]);
 
            // Build the prefix sum
            // at each position in the string
            for (int j = 0 ; j < arr[i].Length ; j++) {
                for (int k = 0 ; k < numElements ; k++) {
                    if(j!=0){
                        elements[i][j, k] = elements[i][j - 1, k];
                    }
                }
 
                // ASCII to int conversion
                // for lowercase letters
                elements[i][j, ((int)arr[i][j] - 97)]++;
            }
        }
 
        // Generate the set of characters
        // which are necessary to remove.
        // Each mapping is the set
        // corresponding of characters
        // which need to be removed.
        // for each letter in order for a
        // subsequence to be generated.
        SortedDictionary<int, SortedSet<int>> requiredRemovals = new SortedDictionary<int, SortedSet<int>>();
        for (int i = 0 ; i < numElements ; i++){
            requiredRemovals.Add(i, new SortedSet<int>());
        }
 
        // Iterate over all the characters
        // (in the alphabet in this case)
        for (int i = 0 ; i < numElements ; i++) {
 
            // For each character,
            // go through all M strings
            // to generate prefix sums
            for (int j = 1 ; j < N ; j++) {
 
                // String a stores
                // the previous string (j-1)
                // string b stores
                // the current string (j)
                String a = arr[j - 1];
                String b = arr[j];
 
                // Store the prefix sums
                // for strings a and b
                int[, ] elements1 = elements[j - 1];
                int[, ] elements2 = elements[j];
 
                int p1 = 0;
                int p2 = 0;
 
                // Check if the lengths of characters
                // differ; if they do, then
                // no valid subsequence
                // with that character can be generated.
                // So for all other letters,
                // add that character to its Set.
                // Otherwise, check the count
                // of each character
                // at every position where
                // letter i appears in both strings
                if (elements1[a.Length - 1, i] != elements2[b.Length - 1, i]) {
                    foreach( KeyValuePair<int, SortedSet<int>> pr in requiredRemovals){
                        requiredRemovals[pr.Key].Add(i);
                    }
                }
                else {
                    // Iterate through both strings
                    // using p1 for all characters
                    // in the first string
                    // and p2 for all characters
                    // in the second string
                    while (p1 < a.Length && p2 < b.Length) {
 
                        // Skip to the next occurrence of
                        // character i in string a
                        while (p1 < a.Length && ((int)a[p1] - 97) != i) {
                            p1++;
                        }
 
                        // Skip to the next occurrence of
                        // character i in string b
                        while (p2 < b.Length && ((int)b[p2] - 97) != i) {
                            p2++;
                        }
 
                        // Compare the count of each
                        // character to check if they match
                        // in both strings
                        if (p1 < a.Length && p2 < b.Length) {
 
                            // Iterate over
                            // their prefix sums
                            for (int k = 0 ; k < numElements; k++) {
                                if (elements1[p1, k] != elements2[p2, k]){
                                    requiredRemovals[i].Add(k);
                                }
                            }
                        }
                        p1++;
                        p2++;
                    }
                }
            }
        }
 
        List<bool> res = new List<bool>();
 
        // Read in Q queries
        for (int i = 0; i < Q; i++) {
 
            // st = new StringTokenizer(br.readLine());
            // String q = st.nextToken();
            SortedSet<int> union = new SortedSet<int>();
 
            // generate a combined set of all characters
            // which must be removed for a valid subsequence
            // to be created with the query string
            foreach (char c in queries[i].ToCharArray()){
                foreach(int x in requiredRemovals[((int)c - 97)]){
                    union.Add(x);
                }
            }
            bool ans = true;
 
            // if there are any contradictions in the query,
            // then the answer will be false
            foreach (char c in queries[i].ToCharArray()) {
                if (union.Contains((int)c - 97)){
                    ans = false;
                }
            }
 
            res.Add(ans);
        }
        return res;
    }
 
 
    // Driver Code
    public static void Main(string[] args){
         
        int N = 3;
        List<String> arr = new List<String>();
        arr.Add("accbad");
        arr.Add("abcacd");
        arr.Add("cacbda");
 
        int Q = 6;
        String[] queries = new String[6];
        queries[0] = "a";
        queries[1] = "ab";
        queries[2] = "ad";
        queries[3] = "bd";
        queries[4] = "bcd";
        queries[5] = "abd";
 
        // Function call
        List<bool> ans = isPossible(N, arr, Q, queries);
        foreach(bool val in ans){
            Console.Write(val + "\n");
        }
 
    }
}
 
// This code is contributed by subhamgoyal2014.
Producción

true
true
false
true
false
false

Complejidad de Tiempo: O(C 2 * N + Q * N)
Espacio Auxiliar: O(C 2 * N) donde C = 26

Publicación traducida automáticamente

Artículo escrito por mltwo y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *