📌  相关文章
📜  检查给定字符串是否对范围 [1, N] 中的所有 K 都是 K 周期的

📅  最后修改于: 2022-05-13 01:56:12.428000             🧑  作者: Mango

检查给定字符串是否对范围 [1, N] 中的所有 K 都是 K 周期的

给定一个大小为N的字符串str ,任务是检查给定字符串是否为K -periodic ,对于范围[1, N]中的所有 K。如果给定字符串是K-periodic则打印Yes ,否则打印No

例子:

方法:可以使用z 算法解决该任务

  • 让我们为给定的字符串构造 Z 数组。 (0索引)
  • 然后,i 是一个句点,(Ni) 应该等于索引 i 处的 z 值,因为如果 'i' 是字符串的句点之一,那么长度 (Ni) 的后缀与长度的前缀完全匹配(你)。
  • 最后,将 N(字符串的长度)附加到答案中,N 值是微不足道的,上面提到的方法找不到。

下面是上述方法的实现:

C++
// C++ code for the above approach:
#include 
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);
    }
}


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



输出
3 6 7

时间复杂度: O(N)
辅助空间: O(N)