Open In App

Match path of alphabets

Last Updated : 09 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given N cities number from 0 to N – 1. These are connected by M bidirectional roads. The ith road connects two distinct cities Edge[i][0] and Edge[i][1]. We are also given a string s, where s[i] will represent the colour associated with ith city. Each city will have 1 color only. Given Q queries, in the ith query, you are given 3 distinct colours query[i][0], query[i][1], and query[i][2]. For each query return “YES” if there exists a path such that only the city with these three colors comes in the way else return “NO“.

Examples:

Input: N = 6, M = 7, Q = 3, S = “abdebc” , Edge[][] = {{0, 1}, {0, 2}, {1, 3}, {1, 4}, {1, 2}, {2, 4}, {4,5}}, Query[] = {“abc”,”aec”,”azc”}
Output: YES NO NO
Explanation:

  • Query 1: “abc” there exists a path 0 -> 1 -> 4 -> 5 which only consists of colours a, b and c.
  • Query 2: “aec” There is no such path which will contain only a,e,c colours.
  • Query 3: “azc” There is no such path which will contain only a,z,c colours.

Approach: This can be solved with the following idea:

Using Depth First Search technique, we can find path of colours possible from each edge. Store each path in dp. While answering the queries, we can find all possible combination formed from 3 colours. Check whether through dp it is possible or not.

Below are the steps to solve this problem:

  • Create an adjacency list adj[] through edges.
  • Initialize a dp[26][26][26], as there are 3 different colors.
  • Iterate in vertices and mark that node visited.
    • For a node iterate through other nodes, which can be reached.
    • Make a set of colors in the set and store the value in DP.
  • Iterate in queries:
    • For each colours set, make combinations and check whether it exist in dp
      • If exist, Return Yes
      • Otherwise, No
    • Store the answers in ans vector.
  • Return ans.

Below is the implementation of the code:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
 
// Function to iterate in array to
// make color visited
void dfs(int node, unordered_map<int, vector<int> >& adj,
         string& col, set<char>& set, vector<bool>& vis)
{
    // Make the node visited
    vis[node] = 1;
 
    for (auto nbr : adj[node]) {
 
        if (!vis[nbr] && col[nbr] == col[node]) {
            dfs(nbr, adj, col, set, vis);
        }
        else {
            // Insert in set
            set.insert(col[nbr]);
        }
    }
}
 
// Function to match path of string
// according to roads
vector<string> solve(int N, int M, int Q, string col,
                     vector<vector<int> >& Edge,
                     vector<string>& query)
{
    vector<bool> vis(N, false);
 
    // Intialise a dp as there are 3
    // different colors
    int dp[26][26][26] = { 0 };
 
    // Create a adj list
    unordered_map<int, vector<int> > adj;
    for (auto i : Edge) {
        adj[i[0]].push_back(i[1]);
        adj[i[1]].push_back(i[0]);
    }
 
    // Iterate for edges to make color
    for (int i = 0; i < N; i++) {
        if (!vis[i]) {
            set<char> set;
 
            dfs(i, adj, col, set, vis);
 
            for (auto it1 : set) {
                for (auto it2 : set) {
                    // if(it1 != it2)
                    dp[it1 - 'a'][col[i] - 'a'][it2 - 'a']
                        = 1;
                }
            }
        }
    }
 
    // Answering the queires
    vector<string> ans;
 
    for (auto str : query) {
        int a = str[0] - 'a';
        int b = str[1] - 'a';
        int c = str[2] - 'a';
 
        // If path is matched
        if (dp[a][b] || dp[a][b] || dp[b][a]
            || dp[b][a] || dp[a][b] || dp[b][a])
            ans.push_back("YES");
 
        // If path is not matched
        else
            ans.push_back("NO");
    }
    return ans;
}
 
// Driver code
int main()
{
 
    int N = 6;
    int M = 7;
    int Q = 3;
    string col = "abdebc";
 
    vector<vector<int> > Edge
        = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 1, 4 },
            { 1, 2 }, { 2, 4 }, { 4, 5 } };
 
    vector<string> query = { "abc", "aec", "azc" };
 
    // Function call
    vector<string> ans = solve(N, M, Q, col, Edge, query);
 
    for (auto a : ans) {
        cout << a << " ";
    }
    return 0;
}


Java




import java.util.*;
 
public class Main {
 
    // Function to iterate in array to make color visited
    static void dfs(int node, HashMap<Integer, ArrayList<Integer>> adj,
                    String col, HashSet<Character> set, boolean[] vis) {
        // Make the node visited
        vis[node] = true;
 
        for (int nbr : adj.get(node)) {
            if (!vis[nbr] && col.charAt(nbr) == col.charAt(node)) {
                dfs(nbr, adj, col, set, vis);
            } else {
                // Insert in set
                set.add(col.charAt(nbr));
            }
        }
    }
 
    // Function to match path of string according to roads
    static ArrayList<String> solve(int N, int M, int Q, String col,
                                   int[][] Edge, String[] query) {
        boolean[] vis = new boolean[N];
 
        // Initialize a dp as there are 3 different colors
        int[][][] dp = new int[26][26][26];
 
        // Create an adj list
        HashMap<Integer, ArrayList<Integer>> adj = new HashMap<>();
        for (int i = 0; i < N; i++) {
            adj.put(i, new ArrayList<>());
        }
 
        // Iterate for edges to make color
        for (int[] i : Edge) {
            adj.get(i[0]).add(i[1]);
            adj.get(i[1]).add(i[0]);
        }
 
        // Iterate through edges to make color
        for (int i = 0; i < N; i++) {
            if (!vis[i]) {
                HashSet<Character> set = new HashSet<>();
                dfs(i, adj, col, set, vis);
 
                for (char it1 : set) {
                    for (char it2 : set) {
                        dp[it1 - 'a'][col.charAt(i) - 'a'][it2 - 'a'] = 1;
                    }
                }
            }
        }
 
        // Answering the queries
        ArrayList<String> ans = new ArrayList<>();
 
        for (String str : query) {
            int a = str.charAt(0) - 'a';
            int b = str.charAt(1) - 'a';
            int c = str.charAt(2) - 'a';
 
            // If path is matched
            if (dp[a][b] == 1 || dp[a][b] == 1 || dp[b][a] == 1 ||
                dp[b][a] == 1 || dp[a][b] == 1 || dp[b][a] == 1) {
                ans.add("YES");
            } else {
                ans.add("NO");
            }
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args) {
        int N = 6;
        int M = 7;
        int Q = 3;
        String col = "abdebc";
 
        int[][] Edge = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 1, 4 }, { 1, 2 }, { 2, 4 }, { 4, 5 } };
 
        String[] query = { "abc", "aec", "azc" };
 
        // Function call
        ArrayList<String> ans = solve(N, M, Q, col, Edge, query);
 
        for (String a : ans) {
            System.out.print(a + " ");
        }
    }
}


Python3




from collections import defaultdict
 
# Function to iterate in array to
# make color visited
def dfs(node, adj, col, color_set, vis):
    # Make the node visited
    vis[node] = 1
 
    for nbr in adj[node]:
        if not vis[nbr] and col[nbr] == col[node]:
            dfs(nbr, adj, col, color_set, vis)
        else:
            # Insert in set
            color_set.add(col[nbr])
 
# Function to match path of string
# according to roads
def solve(N, M, Q, col, Edge, query):
    vis = [False] * N
 
    # Initialize a dp as there are 3
    # different colors
    dp = [[[0] * 26 for _ in range(26)] for _ in range(26)]
 
    # Create an adjacency list
    adj = defaultdict(list)
    for i in Edge:
        adj[i[0]].append(i[1])
        adj[i[1]].append(i[0])
 
    # Iterate for edges to make color
    for i in range(N):
        if not vis[i]:
            color_set = set()
            dfs(i, adj, col, color_set, vis)
 
            for it1 in color_set:
                for it2 in color_set:
                    # if(it1 != it2)
                    dp[ord(it1) - ord('a')][ord(col[i]) - ord('a')][ord(it2) - ord('a')] = 1
 
    # Answering the queries
    ans = []
 
    for string in query:
        a = ord(string[0]) - ord('a')
        b = ord(string[1]) - ord('a')
        c = ord(string[2]) - ord('a')
 
        # If path is matched
        if dp[a][b] or dp[a][b] or dp[b][a] or dp[b][a] or dp[a][b] or dp[b][a]:
            ans.append("YES")
        # If path is not matched
        else:
            ans.append("NO")
 
    return ans
 
# Driver code
if __name__ == "__main__":
    N = 6
    M = 7
    Q = 3
    col = "abdebc"
 
    Edge = [[0, 1], [0, 2], [1, 3], [1, 4], [1, 2], [2, 4], [4, 5]]
 
    query = ["abc", "aec", "azc"]
 
    # Function call
    ans = solve(N, M, Q, col, Edge, query)
 
    for a in ans:
        print(a, end=" ")


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
    // Function to iterate in array to
    // make color visited
    static void DFS(int node,
                    Dictionary<int, List<int> > adj,
                    ref string col, ref HashSet<char> set,
                    ref List<bool> vis)
    {
        // Make the node visited
        vis[node] = true;
 
        foreach(var nbr in adj[node])
        {
            if (!vis[nbr] && col[nbr] == col[node]) {
                DFS(nbr, adj, ref col, ref set, ref vis);
            }
            else {
                // Insert in set
                set.Add(col[nbr]);
            }
        }
    }
 
    // Function to match path of string
    // according to roads
    static List<string> Solve(int N, int M, int Q,
                              string col,
                              List<List<int> > Edge,
                              List<string> query)
    {
        List<bool> vis = new List<bool>(new bool[N]);
 
        // Intialise a dp as there are 3
        // different colors
        int[, , ] dp = new int[26, 26, 26];
 
        // Create an adj list
        Dictionary<int, List<int> > adj
            = new Dictionary<int, List<int> >();
        foreach(var i in Edge)
        {
            if (!adj.ContainsKey(i[0]))
                adj[i[0]] = new List<int>();
            if (!adj.ContainsKey(i[1]))
                adj[i[1]] = new List<int>();
 
            adj[i[0]].Add(i[1]);
            adj[i[1]].Add(i[0]);
        }
 
        // Iterate for edges to make color
        for (int i = 0; i < N; i++) {
            if (!vis[i]) {
                HashSet<char> set = new HashSet<char>();
 
                DFS(i, adj, ref col, ref set, ref vis);
 
                foreach(var it1 in set)
                {
                    foreach(var it2 in set)
                    {
                        // if(it1 != it2)
                        dp[it1 - 'a', col[i] - 'a',
                           it2 - 'a']
                            = 1;
                    }
                }
            }
        }
 
        // Answering the queries
        List<string> ans = new List<string>();
 
        foreach(var str in query)
        {
            int a = str[0] - 'a';
            int b = str[1] - 'a';
            int c = str[2] - 'a';
 
            // If path is matched
            if (dp[a, b, c] != 0 || dp[a, c, b] != 0
                || dp[b, a, c] != 0 || dp[b, c, a] != 0
                || dp != 0 || dp != 0)
                ans.Add("YES");
 
            // If path is not matched
            else
                ans.Add("NO");
        }
        return ans;
    }
 
    // Driver code
    public static void Main()
    {
 
        int N = 6;
        int M = 7;
        int Q = 3;
        string col = "abdebc";
 
        List<List<int> > Edge = new List<List<int> >{
            new List<int>{ 0, 1 }, new List<int>{ 0, 2 },
            new List<int>{ 1, 3 }, new List<int>{ 1, 4 },
            new List<int>{ 1, 2 }, new List<int>{ 2, 4 },
            new List<int>{ 4, 5 }
        };
 
        List<string> query
            = new List<string>{ "abc", "aec", "azc" };
 
        // Function call
        List<string> ans = Solve(N, M, Q, col, Edge, query);
 
        foreach(var a in ans) { Console.Write(a + " "); }
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




// Javascript program for the above approach
 
// Function to iterate in array to
// make color visited
function DFS(node, adj, col, colorSet, vis) {
    // Make the node visited
    vis[node] = true;
 
    // Convert Map values to an array for iteration
    const neighbors = Array.from(adj.get(node) || []);
 
    for (const nbr of neighbors) {
        if (!vis[nbr] && col[nbr] === col[node]) {
            DFS(nbr, adj, col, colorSet, vis);
        } else {
            // Insert in set
            colorSet.add(col[nbr]);
        }
    }
}
 
// Function to match path of string
// according to roads
function Solve(N, M, Q, col, Edge, query) {
    const vis = Array(N).fill(false);
 
    // Intialise a dp as there are 3
    // different colors
    const dp = Array.from({ length: 26 }, () =>
        Array.from({ length: 26 }, () => Array(26).fill(0))
    );
 
    // Create an adj list
    const adj = new Map();
    for (const i of Edge) {
        if (!adj.has(i[0])) adj.set(i[0], []);
        if (!adj.has(i[1])) adj.set(i[1], []);
        adj.get(i[0]).push(i[1]);
        adj.get(i[1]).push(i[0]);
    }
 
    // Iterate for edges to make color
    for (let i = 0; i < N; i++) {
        if (!vis[i]) {
            const colorSet = new Set();
 
            DFS(i, adj, col, colorSet, vis);
 
            for (const it1 of colorSet) {
                for (const it2 of colorSet) {
                    // if(it1 != it2)
                    dp[it1.charCodeAt() - 'a'.charCodeAt()][col[i].charCodeAt() - 'a'.charCodeAt()][it2.charCodeAt() - 'a'.charCodeAt()] = 1;
                }
            }
        }
    }
 
    // Answering the queries
    const ans = [];
 
    for (const str of query) {
        const a = str.charCodeAt(0) - 'a'.charCodeAt();
        const b = str.charCodeAt(1) - 'a'.charCodeAt();
        const c = str.charCodeAt(2) - 'a'.charCodeAt();
 
        // If path is matched
        if (dp[a][b] !== 0 || dp[a][b] !== 0 || dp[b][a] !== 0 || dp[b][a] !== 0 || dp[a][b] !== 0 || dp[b][a] !== 0) ans.push("YES");
        // If path is not matched
        else ans.push("NO");
    }
    return ans;
}
 
// Driver code
const N = 6;
const M = 7;
const Q = 3;
const col = "abdebc";
 
const Edge = [
    [0, 1], [0, 2], [1, 3],
    [1, 4], [1, 2], [2, 4],
    [4, 5]
];
 
const query = ["abc", "aec", "azc"];
 
// Function call
const ans = Solve(N, M, Q, col, Edge, query);
 
console.log(ans.join(" "));
 
// This code is contributed by Susobhan Akhuli


Output

YES NO NO 









Time Complexity: O(N * M + Q)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads