Compruebe si String se puede convertir en palíndromo reemplazando caracteres en pares dados

Dada una string str y un par de caracteres K , la tarea es verificar si la string str puede convertirse en palíndromo , reemplazando un carácter de cada par con el otro.

Ejemplos:

Entrada: str = “geeks”, K = 2, pares = [[“g”, “s”], [“k”, “e”]]
Salida : Verdadero
Explicación: 
Intercambiar ‘s’ de “geeks” con ‘ g’ usando par [‘g’, ‘s’] = “geekg”
Intercambiar ‘k’ de “geekg” con ‘e’ usando par [‘k’, ‘e’] = “geeeg”
Ahora la string resultante es una palíndromo. Por lo tanto, la salida será True.

Entrada : str = “geeks”, K = 1, pares = [[“g”, “s”]]
Salida: Falso
Explicación: Aquí solo se puede intercambiar el primer carácter (g, s)
La string final formada será: geekg , que no es un palíndromo.

 

Enfoque ingenuo : el problema dado se puede resolver creando un gráfico no dirigido donde un borde que conecta (x, y) representa una relación entre los caracteres x e y.

  • Verifique la condición del palíndromo validando los primeros semicaracteres con los semicaracteres posteriores.
  • Si no es igual:
    • Ejecute un dfs desde el primer carácter y verifique si se puede alcanzar el último carácter.
  • Luego, verifique el segundo carácter con el penúltimo carácter y así sucesivamente.

Complejidad de tiempo: O(N * M), donde N es el tamaño de la string objetivo y M es el tamaño de la array de pares
Espacio auxiliar: O(1)

Enfoque eficiente: el problema se puede resolver de manera eficiente con la ayuda de la siguiente idea:

Utilice una estructura de datos de conjuntos disjuntos donde cada par [i][0] y par [i][1] se puedan unir bajo el mismo conjunto y la operación de búsqueda se pueda realizar de manera eficiente. 
En lugar de buscar los caracteres cada vez, intente agrupar todos los caracteres que están conectados directa o indirectamente en el mismo conjunto.

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

C++

#include <iostream>
#include <string>
#include <vector>
using namespace std;
 
// Structure for Disjoint set union
struct disjoint_set {
    vector<int> parent, rank;
 
    // Initialize DSU variables
    disjoint_set()
    {
        parent.resize(26);
        rank.resize(26);
        for (int i = 0 ; i < 26 ; i++) {
            parent[i] = i;
            rank[i] = 1;
        }
    }
 
    // Find parent of vertex 'v'
    int find_parent(int v)
    {
        if (v == parent[v])
            return v;
        return parent[v] = find_parent(parent[v]);
    }
 
    // Union two sets containing vertices a and b
    void Union(int p1, int p2)
    {
        p1 = find_parent(p1);
        p2 = find_parent(p2);
  
        if (p1 != p2){
  
            // rank of p1 smaller than p2
            if(rank[p1] < rank[p2]){
                parent[p1] = p2;
  
            }else if(rank[p2] < rank[p1]){
                parent[p2] = p1;
  
            // rank of p2 equal to p1
            }else{
                parent[p2] = p1;
                rank[p1] += 1;
            }
        }
    }
 
    // Function for checking whether
    // vertex a and b are in same set or not
    bool connected(int p1, int p2)
    {
        p1 = find_parent(p1);
        p2 = find_parent(p2);
        if(p1 == p2) return true;
        return false;
    }
};
 
// Function solving the problem
bool solve(string& target, vector<pair<char, char> >& pairs)
{
 
    // Initialize new instance of DSU
    disjoint_set dsu; // Only lowercase letters
 
    for (auto i : pairs) {
        dsu.Union(i.first - 'a', i.second - 'a');
    }
 
    int lower = 0, upper = (int)target.length() - 1;
 
    while (lower <= upper) {
        if (!dsu.connected(target[lower] - 'a', target[upper] - 'a')) {
            return false;
        }
        lower+=1;
        upper-=1;
    }
 
    return true;
}
 
// Driver code
int main()
{
 
    string target = "geeks";
    vector<pair<char, char> > pairs
        = { { 'g', 's' }, { 'e', 'k' } };
 
    bool ans = solve(target, pairs);
 
    if (ans) {
        cout << "true\n";
    }
    else {
        cout << "false\n";
    }
    return 0;
}
 
// This code is contributed by subhamgoyal2014.

Python3

# Python code for the above approach:
 
class disjoint_set():
    def __init__(self):
 
        # string consist of only smallcase letters
        self.parent = [i for i in range(26)]
        self.rank = [1 for i in range(26)]
 
    def find_parent(self, x):
        if (self.parent[x] == x):
            return x
 
        self.parent[x] = self.find_parent(self.parent[x])
        return (self.parent[x])
 
    def union(self, u, v):
 
        p1 = self.find_parent(u)
        p2 = self.find_parent(v)
 
        if (p1 != p2):
 
            # rank of p1 smaller than p2
            if(self.rank[p1] < self.rank[p2]):
                self.parent[p1] = p2
 
            elif(self.rank[p2] < self.rank[p1]):
                self.parent[p2] = p1
 
            # rank of p2 equal to p1
            else:
                self.parent[p2] = p1
                self.rank[p1] += 1
 
    def connected(self, w1, w2):
 
        p1 = self.find_parent(w1)
        p2 = self.find_parent(w2)
 
        if (p1 == p2):
            return True
 
        return False
 
 
class Solution:
    def solve(self, target, pairs):
 
        size = len(target)
 
        # Create a object of disjoint set
        dis_obj = disjoint_set()
 
        for (u, v) in pairs:
 
            ascii_1 = ord(u) - ord('a')
            ascii_2 = ord(v) - ord('a')
 
            # Take union of both the characters
            dis_obj.union(ascii_1, ascii_2)
 
        left = 0
        right = size-1
 
        # Check for palindrome condition
        # For every character
        while(left < right):
 
            s1 = target[left]
            s2 = target[right]
 
            # If characters not same
            if (s1 != s2):
 
                # Convert to ascii value between 0-25
                ascii_1 = ord(s1) - ord('a')
                ascii_2 = ord(s2) - ord('a')
 
                # Check if both the words
                # Belong to same set
                if (not dis_obj.connected(ascii_1, ascii_2)):
                    return False
 
            left += 1
            right -= 1
 
        # Finally return True
        return (True)
 
 
if __name__ == '__main__':
 
    target = "geeks"
    pairs = [["g", "s"], ["e", "k"]]
 
    obj = Solution()
 
    ans = obj.solve(target, pairs)
    if (ans):
        print('true')
 
    else:
        print('false')

Javascript

<script>
 
// JavaScript code for the above approach:
 
class disjoint_set{
    constructor(){
 
        // string consist of only smallcase letters
        this.parent = new Array(26)
        for(let i=0;i<26;i++){
            this.parent[i] = i
        }
        this.rank = new Array(26).fill(1)
    }
 
    find_parent(x){
        if (this.parent[x] == x)
            return x
 
        this.parent[x] = this.find_parent(this.parent[x])
        return (this.parent[x])
    }
 
    union(u, v){
 
        let p1 = this.find_parent(u)
        let p2 = this.find_parent(v)
 
        if (p1 != p2){
 
            // rank of p1 smaller than p2
            if(this.rank[p1] < this.rank[p2])
                this.parent[p1] = p2
 
            else if(this.rank[p2] < this.rank[p1])
                this.parent[p2] = p1
 
            // rank of p2 equal to p1
            else{
                this.parent[p2] = p1
                this.rank[p1] += 1
            }
        }
    }
 
    connected(w1, w2){
 
        let p1 = this.find_parent(w1)
        let p2 = this.find_parent(w2)
 
        if (p1 == p2)
            return true
 
        return false
    }
}
 
class Solution{
    solve(target, pairs){
 
        let size = target.length
 
        // Create a object of disjoint set
        let dis_obj = new disjoint_set()
 
        for (let [u, v] of pairs){
 
            let ascii_1 = (u).charCodeAt(0) - ('a').charCodeAt(0)
            let ascii_2 = (v).charCodeAt(0) - ('a').charCodeAt(0)
 
            // Take union of both the characters
            dis_obj.union(ascii_1, ascii_2)
        }
 
        let left = 0
        let right = size-1
 
        // Check for palindrome condition
        // For every character
        while(left < right){
 
            let s1 = target[left]
            let s2 = target[right]
 
            // If characters not same
            if (s1 != s2){
 
                // Convert to ascii value between 0-25
                let ascii_1 = s1.charCodeAt(0) - 'a'.charCodeAt(0)
                let ascii_2 = s2.charCodeAt(0) - 'a'.charCodeAt(0)
 
                // Check if both the words
                // Belong to same set
                if (!dis_obj.connected(ascii_1, ascii_2))
                    return false
            }
 
            left += 1
            right -= 1
        }
 
        // Finally return true
        return true
    }
}
 
// driver code
 
let target = "geeks"
let pairs = [["g", "s"], ["e", "k"]]
 
let obj = new Solution()
 
let ans = obj.solve(target, pairs)
if (ans)
    document.write('true')
else
    document.write('false')
 
// This code is contributed by shinjanpatra
 
</script>
Producción

true

Complejidad temporal: O(N)
Espacio auxiliar: O(1)

Publicación traducida automáticamente

Artículo escrito por chantya17 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 *