Find the numbers of strings that can be formed after processing Q queries

Given a number N(1<=N<=2000)., The task is to find the number strings of size N that can be obtained after using characters from 'a' to 'z' and by processing the given q(1<=q<=200000) queries.

For each query given two integers L, R (0<=L<=R<=N) such that substring [L, R] of the generated string of size N must be a palindrome. The task is to process all queries and generate a string of size N such that the substrings of this string defined by all queries are palindrome.

The answer can be very large. So, output answer modulo 1000000007.



Note: 1-based indexing is considered for the string.

Examples:

Input : N = 3
query 1: (1, 2)
query 2: (2, 3)
Output : 26
Explanation : Substring 1 to 2 should be 
palindrome and substring 2 to 3 should be palindrome. so, all 
three characters should be same. so, we can obtain 26 such strings.

Input : N = 4
query 1: (1, 3)
query 2: (2, 4)
Output : 676
Explanation : substring 1 to 3 should be 
palindrome and substring 2 to 4 should be a palindrome. 
So, a first and third character should be the same and 
second and the fourth should be the same. So, we can 
obtain 26*26 such strings.

Approach : An efficient solution is to use union-find algorithm.

  • Find the mid-point of each range (query) and if there are many queries having the same mid-point then only retain that query whose length is max, i.e (where r – l is max).
  • This would have reduced the number of queries to 2*N at max since there is a 2*N number of mid-points in a string of length N.
  • Now for each query do union of element l with r, (l + 1) with (r – 1), (l + 2) with (r – 2) and so on. We do this because the character which would be put on the index l would be the same as the one we put on index r. Extending this logic to all queries we need to maintain disjoint-set data structure. So basically all the elements of one component of disjoint-set should have the same letter on them.
  • After processing all the queries, let the number of disjoint-set components be x, then the answer is 26^x
  • .

    Below is the implementation of the above approach :

    C++

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // C++ program to implement above approach
      
    #include <bits/stdc++.h>
    using namespace std;
    #define N 2005
    #define mod (int)(1e9 + 7)
      
    // To store the size of string and
    // number of queries
    int n, q;
      
    // To store parent and rank of ith place
    int par[N], Rank[N];
      
    // To store maximum interval
    map<int, int> m;
      
    // Function for initialization
    void initialize()
    {
        for (int i = 0; i <= n; i++) {
            par[i] = i;
            Rank[i] = 0;
        }
    }
      
    // Function to find parent
    int find(int x)
    {
        if (par[x] != x)
            par[x] = find(par[x]);
      
        return par[x];
    }
      
    // Function to make union
    void Union(int x, int y)
    {
        int xpar = find(x);
        int ypar = find(y);
      
        if (Rank[xpar] < Rank[ypar])
            par[xpar] = ypar;
        else if (Rank[xpar] > Rank[ypar])
            par[ypar] = xpar;
        else {
            par[ypar] = xpar;
            Rank[xpar]++;
        }
    }
      
    // Power function to calculate a raised to m1
    // under modulo 10000007
    int power(long long a, long long m1)
    {
        if (m1 == 0)
            return 1;
        else if (m1 == 1)
            return a;
        else if (m1 == 2)
            return (1LL * a * a) % mod;
        else if (m1 & 1)
            return (1LL * a * power(power(a, m1 / 2), 2)) % mod;
        else
            return power(power(a, m1 / 2), 2) % mod;
    }
      
    // Function to take maxmium interval
    void query(int l, int r)
    {
        m[l + r] = max(m[l + r], r);
    }
      
    // Function to find different possible strings
    int possiblestrings()
    {
        initialize();
      
        for (auto i = m.begin(); i != m.end(); i++) {
            int x = i->first - i->second;
            int y = i->second;
      
            // make union of all chracters which
            // are meant to be same
            while (x < y) {
                Union(x, y);
                x++;
                y--;
            }
        }
      
        // find number of different sets formed
        int ans = 0;
        for (int i = 1; i <= n; i++)
            if (par[i] == i)
                ans++;
      
        // return the required answer
        return power(26, ans) % mod;
    }
      
    // Driver Code
    int main()
    {
        n = 4;
      
        // queries
        query(1, 3);
        query(2, 4);
      
        cout << possiblestrings();
      
        return 0;
    }

    chevron_right

    
    

    Java

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Java program to implement above approach
    import java.util.*;
      
    class GFG 
    {
        static final int N = 2005;
        static final int mod = 1000000007;
      
        // To store the size of string and
        // number of queries
        static int n, q;
      
        // To store parent and rank of ith place
        static int[] par = new int[N], Rank = new int[N];
      
        // To store maximum interval
        static HashMap<Integer,
                       Integer> m = new HashMap<>();
      
        // Function for initialization
        static void initialize()
        {
            for (int i = 0; i <= n; i++)
            {
                par[i] = i;
                Rank[i] = 0;
            }
        }
      
        // Function to find parent
        static int find(int x)
        {
            if (par[x] != x)
                par[x] = find(par[x]);
      
            return par[x];
        }
      
        // Function to make union
        static void Union(int x, int y) 
        {
            int xpar = find(x);
            int ypar = find(y);
      
            if (Rank[xpar] < Rank[ypar])
                par[xpar] = ypar;
            else if (Rank[xpar] > Rank[ypar])
                par[ypar] = xpar;
            else 
            {
                par[ypar] = xpar;
                Rank[xpar]++;
            }
        }
      
        // Power function to calculate a raised to m1
        // under modulo 10000007
        static long power(long a, long m1) 
        {
            if (m1 == 0)
                return 1;
            else if (m1 == 1)
                return a;
            else if (m1 == 2)
                return (1L * a * a) % mod;
            else if (m1 % 2 == 1)
                return (1L * a * power(power(a, m1 / 2), 2)) % mod;
            else
                return power(power(a, m1 / 2), 2) % mod;
        }
      
        // Function to take maxmium interval
        static void query(int l, int r)
        {
            if (m.containsKey(l + r))
                m.put(l + r, Math.max(m.get(l + r), r));
            else
                m.put(l + r, r);
        }
      
        // Function to find different possible strings
        static long possiblestrings() 
        {
            initialize();
      
            for (Integer i : m.keySet())
            {
                int x = i - m.get(i);
                int y = m.get(i);
      
                // make union of all chracters which
                // are meant to be same
                while (x < y) 
                {
                    Union(x, y);
                    x++;
                    y--;
                }
            }
      
            // find number of different sets formed
            int ans = 0;
            for (int i = 1; i <= n; i++)
                if (par[i] == i)
                    ans++;
      
            // return the required answer
            return power(26, ans) % mod;
        }
      
        // Driver Code
        public static void main(String[] args) 
        {
            n = 4;
      
            // queries
            query(1, 3);
            query(2, 4);
      
            System.out.println(possiblestrings());
        }
    }
      
    // This code is contributed by
    // sanjeev2552

    chevron_right

    
    

    Python3

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # Python3 program to implement above approach
    N = 2005
    mod = 10**9 + 7
      
    # To store the size of string and
    # number of queries
    n, q = 0, 0
      
    # To store parent and rank of ith place
    par = [0 for i in range(N)]
    Rank = [0 for i in range(N)]
      
    # To store maximum interval
    m = dict()
      
    # Function for initialization
    def initialize():
      
        for i in range(n + 1):
            Rank[i], par[i] = 0, i
      
    # Function to find parent
    def find(x):
        if (par[x] != x):
            par[x] = find(par[x])
      
        return par[x]
      
    # Function to make union
    def Union(x, y):
      
        xpar = find(x)
        ypar = find(y)
      
        if (Rank[xpar] < Rank[ypar]):
            par[xpar] = ypar
        elif (Rank[xpar] > Rank[ypar]):
            par[ypar] = xpar
        else:
            par[ypar] = xpar
            Rank[xpar] += 1
      
    # Power function to calculate a raised to m1
    # under modulo 10000007
    def power(a, m1):
      
        if (m1 == 0):
            return 1
        elif (m1 == 1):
            return a
        elif (m1 == 2):
            return (a * a) % mod
        elif (m1 & 1):
            return (a * power(power(a, m1 // 2), 2)) % mod
        else:
            return power(power(a, m1 // 2), 2) % mod
      
    # Function to take maxmium interval
    def query(l, r):
        if l + r in m.keys():
            m[l + r] = max(m[l + r], r)
        else:
            m[l + r] = max(0, r)
      
    # Function to find different possible strings
    def possiblestrings():
        initialize()
      
        for i in m:
            x = i - m[i]
            y = m[i]
      
            # make union of all chracters which
            # are meant to be same
            while (x < y):
                Union(x, y)
                x += 1
                y -= 1
      
        # find number of different sets formed
        ans = 0
        for i in range(1, n + 1):
            if (par[i] == i):
                ans += 1
      
        # return the required answer
        return power(26, ans) % mod
      
    # Driver Code
    n = 4
      
    # queries
    query(1, 3)
    query(2, 4)
      
    print(possiblestrings())
      
    # This code is contributed by Mohit Kumar

    chevron_right

    
    

    Output:

    676
    


    My Personal Notes arrow_drop_up

    pawanasipugmailcom

    If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

    Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.