Open In App

Check if given String is K-periodic for all K in range [1, N]

Last Updated : 29 Mar, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string str of size N, the task is to check whether the given string is K-periodic, for all Ks in range [1, N]. Print Yes if the given string is K-periodic, else print No.

A string is K-periodic, if the string is a repetition of the sub-string str[0 … k-1].

For example, the string “ababab” is 2-periodic. 

Examples:

Input: N = 7,  S = “abcabca”
Output: 3 6 7
Explanation: 
1. Consider prefix of length 1 (i.e. “a”), then if we repeat this prefix to make a string of length 7, we get “aaaaaaa” which is not equal to the original string.
2. Consider prefix of length 2 (i.e. “ab”), then if we repeat this prefix to make a string of length 7, we get “abababa” which is not equal to the original string.
3. Consider prefix of length 3 (i.e. “abc”), then if we repeat this prefix to make a string of length 7, we get “abcabca” which is equal to the original string.
4. Consider prefix of length 4 (i.e. “abca”), then if we repeat this prefix to make a string of length 7, we get “abcaabc” which is not equal to the original string.
5. Consider prefix of length 5 (i.e. “abcab”), then if we repeat this prefix to make a string of length 7, we get “abcabab” which is not equal to the original string.
6. Consider prefix of length 6 (i.e. “abcabc”), then if we repeat this prefix to make a string of length 7, we get “abcabca” which is equal to the original string.
7. Consider prefix of length 7 (i.e. “abcabca”), then if we repeat this prefix to make a string of length 7, we get “abcabca” which is equal to the original string.

Input: N = 5, S = “aaaaa”
Output: 1 2 3 4 5
Explanation:   As all the characters of the given string are same hence, the string can be generated by repeating the prefix of length 1 to N.

 

Approach: The task can be solved using z-algorithm.

  • Let’s construct Z array for the given string. (0-indexed)
  • Then, i to be a period, (N-i) should be equal to the z value at index i, because if ‘i’ is one of the period of the string, then a suffix of length (N-i) exactly matches with prefix of length (n-i).
  • At last, append N (length of the string) to the answer, the N value is trivial which the above mentioned method doesn’t find.

Below is the implementation of the above approach:

C++




// C++ code for the above approach:
#include <iostream>
using namespace std;
 
void getZarr(string str, int Z[]);
 
// Prints all the period of a string
void findPeriod(string text)
{
    int l = text.length();
 
    // Construct Z array
    int Z[l];
    getZarr(text, Z);
 
    // Now looping through Z array
    // For finding period
    for (int i = 1; i < l; ++i) {
 
        // If(l-i) is equal to Z[i],
        // Then one of the period
        // Of string is i
        if (Z[i] == (l - i))
            cout << i << " ";
    }
 
    // Print trivial value
    //(i.e. length of string)
    cout << l << endl;
}
 
// Fills Z array for given string str[]
void getZarr(string str, int Z[])
{
    int n = str.length();
    int L, R, k;
 
    // [L, R] make a window
    // Which matches with prefix of s
    L = R = 0;
    for (int i = 1; i < n; ++i) {
        // If i>R nothing matches
        // So we will calculate.
        // Z[i] using naive way.
        if (i > R) {
            L = R = i;
 
            // R-L = 0 in starting, so it will start
            // Checking from 0'th index. For example,
            // For "ababab" and i = 1, the value of R
            // Remains 0 and Z[i] becomes 0. For string
            // "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n && str[R - L] == str[R])
                R++;
            Z[i] = R - L;
            R--;
        }
        else {
            // k = i-L so k corresponds to number
            // Which matches in [L, R] interval.
            k = i - L;
 
            // If Z[k] is less than remaining interval
            // Then Z[i] will be equal to Z[k].
            // For example, str = "ababab", i = 3, R = 5
            // and L = 2
            if (Z[k] < R - i + 1)
                Z[i] = Z[k];
 
            // For example str = "aaaaaa"
            // and i = 2, R is 5, L is 0
            else {
 
                // Else start from R
                // And check manually
                L = i;
                while (R < n && str[R - L] == str[R])
                    R++;
                Z[i] = R - L;
                R--;
            }
        }
    }
}
 
// Driver code
int main()
{
    string text = "abcabca";
    findPeriod(text);
    return 0;
}


Java




// A Java program that implements Z algorithm for period
// finding
class GFG {
 
    // prints all the period of string
    public static void findPeriod(String text)
    {
 
        int l = text.length();
 
        int Z[] = new int[l];
 
        // Construct Z array
        getZarr(text, Z);
 
        // now looping through Z array for finding period
        for (int i = 0; i < l; ++i) {
 
            // if Z[i] is equal to (l-i), then one
            // of the period of string is i
 
            if (Z[i] == (l - i)) {
                System.out.print(i + " ");
            }
        }
 
        // Print trivial value (i.e. length of string)
        System.out.println(l);
    }
 
    // Fills Z array for given string str[]
    private static void getZarr(String str, int[] Z)
    {
 
        int n = str.length();
 
        // [L, R] make a window which matches with
        // prefix of s
        int L = 0, R = 0;
 
        for (int i = 1; i < n; ++i) {
 
            // if i>R nothing matches so we will calculate.
            // Z[i] using naive way.
            if (i > R) {
 
                L = R = i;
 
                // R-L = 0 in starting, so it will start
                // checking from 0'th index. For example,
                // for "ababab" and i = 1, the value of R
                // remains 0 and Z[i] becomes 0. For string
                // "aaaaaa" and i = 1, Z[i] and R become 5
 
                while (R < n && str.charAt(R - L) == str.charAt(R))
                    R++;
 
                Z[i] = R - L;
                R--;
            }
            else {
 
                // k = i-L so k corresponds to number which
                // matches in [L, R] interval.
                int k = i - L;
 
                // if Z[k] is less than remaining interval
                // then Z[i] will be equal to Z[k].
                // For example, str = "ababab", i = 3, R = 5
                // and L = 2
                if (Z[k] < R - i + 1)
                    Z[i] = Z[k];
 
                // For example str = "aaaaaa" and i = 2, R is 5,
                // L is 0
                else {
 
                    // else start from R and check manually
                    L = i;
                    while (R < n && str.charAt(R - L) == str.charAt(R))
                        R++;
 
                    Z[i] = R - L;
                    R--;
                }
            }
        }
    }
 
    // Driver program
    public static void main(String[] args)
    {
        String text = "abcabca";
 
        findPeriod(text);
    }
}


Python3




# python3 code for the above approach:
 
# Fills Z array for given string str[]
def getZarr(str, Z):
 
    n = len(str)
    L, R, k = 0, 0, 0
 
    # [L, R] make a window
    # Which matches with prefix of s
 
    for i in range(1, n):
        # If i>R nothing matches
        # So we will calculate.
        # Z[i] using naive way.
        if (i > R):
            L = R = i
 
            # R-L = 0 in starting, so it will start
            # Checking from 0'th index. For example,
            # For "ababab" and i = 1, the value of R
            # Remains 0 and Z[i] becomes 0. For string
            # "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n and str[R - L] == str[R]):
                R += 1
            Z[i] = R - L
            R -= 1
 
        else:
            # k = i-L so k corresponds to number
            # Which matches in [L, R] interval.
            k = i - L
 
            # If Z[k] is less than remaining interval
            # Then Z[i] will be equal to Z[k].
            # For example, str = "ababab", i = 3, R = 5
            # and L = 2
            if (Z[k] < R - i + 1):
                Z[i] = Z[k]
 
            # For example str = "aaaaaa"
            # and i = 2, R is 5, L is 0
            else:
 
                # Else start from R
                # And check manually
                L = i
                while (R < n and str[R - L] == str[R]):
                    R += 1
                Z[i] = R - L
                R -= 1
 
 
# Prints all the period of a string
def findPeriod(text):
 
    l = len(text)
 
    # Construct Z array
    Z = [0 for _ in range(l)]
    getZarr(text, Z)
 
    # Now looping through Z array
    # For finding period
    for i in range(1, l):
 
        # If(l-i) is equal to Z[i],
        # Then one of the period
        # Of string is i
        if (Z[i] == (l - i)):
            print(i, end=" ")
 
    # Print trivial value
    # (i.e. length of string)
    print(l)
 
# Driver code
if __name__ == "__main__":
 
    text = "abcabca"
    findPeriod(text)
 
# This code is contributed by rakeshsahni


C#




// C# code for the above approach:
using System;
class GFG {
 
  // Prints all the period of a string
  static void findPeriod(string text)
  {
    int l = text.Length;
 
    // Construct Z array
    int[] Z = new int[l];
    getZarr(text, Z);
 
    // Now looping through Z array
    // For finding period
    for (int i = 1; i < l; ++i) {
 
      // If(l-i) is equal to Z[i],
      // Then one of the period
      // Of string is i
      if (Z[i] == (l - i))
        Console.Write(i + " ");
    }
 
    // Print trivial value
    //(i.e. length of string)
    Console.WriteLine(l);
  }
 
  // Fills Z array for given string str[]
  static void getZarr(string str, int[] Z)
  {
    int n = str.Length;
    int L, R, k;
 
    // [L, R] make a window
    // Which matches with prefix of s
    L = R = 0;
    for (int i = 1; i < n; ++i) {
      // If i>R nothing matches
      // So we will calculate.
      // Z[i] using naive way.
      if (i > R) {
        L = R = i;
 
        // R-L = 0 in starting, so it will start
        // Checking from 0'th index. For example,
        // For "ababab" and i = 1, the value of R
        // Remains 0 and Z[i] becomes 0. For string
        // "aaaaaa" and i = 1, Z[i] and R become 5
        while (R < n && str[R - L] == str[R])
          R++;
        Z[i] = R - L;
        R--;
      }
      else {
        // k = i-L so k corresponds to number
        // Which matches in [L, R] interval.
        k = i - L;
 
        // If Z[k] is less than remaining interval
        // Then Z[i] will be equal to Z[k].
        // For example, str = "ababab", i = 3, R = 5
        // and L = 2
        if (Z[k] < R - i + 1)
          Z[i] = Z[k];
 
        // For example str = "aaaaaa"
        // and i = 2, R is 5, L is 0
        else {
 
          // Else start from R
          // And check manually
          L = i;
          while (R < n && str[R - L] == str[R])
            R++;
          Z[i] = R - L;
          R--;
        }
      }
    }
  }
 
  // Driver code
  public static int Main()
  {
    string text = "abcabca";
    findPeriod(text);
    return 0;
  }
}
 
// This code is contributed by Taranpreet


Javascript




<script>
       // JavaScript code for the above approach
// Fills Z array for given string str[]
function getZarr(str,  Z)
{
    let n = str.length;
    let L, R, k;
 
    // [L, R] make a window
    // Which matches with prefix of s
    L = R = 0;
    for (let i = 1; i < n; ++i) {
        // If i>R nothing matches
        // So we will calculate.
        // Z[i] using naive way.
        if (i > R) {
            L = R = i;
 
            // R-L = 0 in starting, so it will start
            // Checking from 0'th index. For example,
            // For "ababab" and i = 1, the value of R
            // Remains 0 and Z[i] becomes 0. For string
            // "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n && str[R - L] == str[R])
                R++;
            Z[i] = R - L;
            R--;
        }
        else {
            // k = i-L so k corresponds to number
            // Which matches in [L, R] interval.
            k = i - L;
 
            // If Z[k] is less than remaining interval
            // Then Z[i] will be equal to Z[k].
            // For example, str = "ababab", i = 3, R = 5
            // and L = 2
            if (Z[k] < R - i + 1)
                Z[i] = Z[k];
 
            // For example str = "aaaaaa"
            // and i = 2, R is 5, L is 0
            else {
 
                // Else start from R
                // And check manually
                L = i;
                while (R < n && str[R - L] == str[R])
                    R++;
                Z[i] = R - L;
                R--;
            }
        }
    }
}
 
// Prints all the period of a string
function findPeriod(text)
{
    let l = text.length;
 
    // Construct Z array
    let Z= new Array(l);
    getZarr(text, Z);
 
    // Now looping through Z array
    // For finding period
    for (let i = 1; i < l; ++i) {
 
        // If(l-i) is equal to Z[i],
        // Then one of the period
        // Of string is i
        if (Z[i] == (l - i))
            document.write(i + " ")
    }
 
    // Print trivial value
    //(i.e. length of string)
    document.write(l + '<br>')
}
 
// Driver code
 
    let text = "abcabca";
    findPeriod(text);
    
     // This code is contributed by Potta Lokesh
    </script>


 
 

Output

3 6 7

 

Time complexity: O(N)
Auxiliary Space: O(N)

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads