📌  相关文章
📜  通过连接等长前缀和子字符串可以获得的回文数

📅  最后修改于: 2021-05-07 09:47:12             🧑  作者: Mango

先决条件: Z算法

给定字符串S ,任务是查找在执行给定步骤后可以形成的最大回文数:

  1. 选择长度相等的非空前缀P和非空子串T。
  2. 反转PT并将其串联。

注意: P和T可以重叠。

例子:

天真的方法:生成所有可能的前缀和所有可能的子字符串。连接所有等长的前缀和子字符串(反转后)对,并检查获得的字符串是否是回文。

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

高效的方法:可以基于以下观察条件来优化上述方法连接字符串的长度将始终是均匀的。因此,仅需考虑那些字符串,其中前半部分是后半部分的镜像。因此,问题减少到对等于该前缀的每个可能前缀的子字符串进行计数,这可以使用Z函数来完成。

请按照以下步骤解决问题:

  1. 这个想法是要维持一个间隔[l,r] ,该间隔是最大r的间隔,这样[l,r]是一个前缀子串(也是子串的前缀)。
  2. 如果i≤r ,则Z [i]等于r – i + 1Z [i – 1]的最小值
  3. 现在,增量Z [I],直到我+ Z [i]是小于N和字符在指数Z [i]I + Z [I]是给定字符串中相等。
  4. 现在,如果i + Z [i] – 1> r ,则将l设置为i并将r设置i + Z [i] – 1
  5. 0N-1的i重复上述步骤。
  6. 答案是每个i (0≤i≤N-1)Z [i] +1之和。

下面是上述方法的实现:

C++14
// C++ program the above approach
#include 
using namespace std;
 
// Function to calculate the
// number of palindromes
int countPalindromes(string S)
{
    int N = (int)S.length();
    vector Z(N);
 
    // Calculation of Z-array
    int l = 0, r = 0;
    for (int i = 1; i < N; i++) {
 
        if (i <= r)
            Z[i] = min(r - i + 1, Z[i - l]);
 
        while (i + Z[i] < N
               && S[Z[i]] == S[i + Z[i]]) {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r) {
 
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
    for (int i = 0; i < Z.size(); i++) {
        sum += Z[i] + 1;
    }
 
    // Return the count
    return sum;
}
 
// Driver Code
int main()
{
    // Given String
    string S = "abab";
    cout << countPalindromes(S);
 
    return 0;
}


Java
// Java program for the above approach 
import java.util.*;
 
class GFG{
     
// Function to calculate the
// number of palindromes
static int countPalindromes(String S)
{
    int N = (int)S.length();
    int[] Z = new int[(N)];
     
    // Calculation of Z-array
    int l = 0, r = 0;
     
    for(int i = 1; i < N; i++)
    {
        if (i <= r)
            Z[i] = Math.min(r - i + 1,
                              Z[i - l]);
 
        while (i + Z[i] < N &&
               S.charAt(Z[i]) ==
               S.charAt(i + Z[i]))
        {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r)
        {
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
     
    for(int i = 0; i < Z.length; i++)
    {
        sum += Z[i] + 1;
    }
     
    // Return the count
    return sum;
}
 
// Driver Code   
public static void main (String[] args)   
{ 
     
    // Given String
    String S = "abab";
     
    System.out.println(countPalindromes(S));
}
}
 
// This code is contributed by code_hunt


Python3
# Python3 program the above approach
 
# Function to calculate the
# number of palindromes
def countPalindrome(S):
    N = len(S)
    Z = [0] * N
     
    # Calculation of Z-array
    l = 0
    r = 0
    for i in range(1, N):
        if i <= r:
            Z[i] = min(r - i + 1, Z[i - 1])
        while((i + Z[i]) < N and (S[Z[i]] == S[i + Z[i]])):
            Z[i] += 1
        if ((i + Z[i] - 1) > r):
            l = ir = i + Z[i] - 1
             
    # Calculation of sigma(Z[i]+1)
    sum = 0
    for i in range(0, len(Z)):
        sum += Z[i] + 1
     
    # return the count
    return sum
 
# Driver code
 
# Given String
S = "abab"
print(countPalindrome(S))
 
# This code is contributed by virusbuddah


C#
// C# program for the above approach 
using System;
 
public class GFG{
     
// Function to calculate the
// number of palindromes
static int countPalindromes(String S)
{
    int N = (int)S.Length;
    int[] Z = new int[(N)];
     
    // Calculation of Z-array
    int l = 0, r = 0;
     
    for(int i = 1; i < N; i++)
    {
        if (i <= r)
            Z[i] = Math.Min(r - i + 1,
                              Z[i - l]);
        while (i + Z[i] < N &&
               S[Z[i]] ==
               S[i + Z[i]])
        {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r)
        {
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
     
    for(int i = 0; i < Z.Length; i++)
    {
        sum += Z[i] + 1;
    }
     
    // Return the count
    return sum;
}
 
// Driver Code   
public static void Main(String[] args)   
{ 
     
    // Given String
    String S = "abab";
     
    Console.WriteLine(countPalindromes(S));
}
}
 
// This code is contributed by 29AjayKumar


输出:
6

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