📜  计算琴弦的回文特征

📅  最后修改于: 2021-05-04 09:27:00             🧑  作者: Mango

给定长度为n的字符串s,计算具有不同回文特征类型的子字符串的数量。
回文特征是字符串中的k回文数,其中k处于[0,n)范围内。
当且仅当字符串向后读取与向后读取相同时,它才是1-回文(或简称回文)。
字符串仅在以下情况下为k回文式(k> 1):
1.它的左半部分等于其右半部分。
2.其左半部分和右半部分应为非空(k – 1)回文。长度为’t’的字符串的左半部分是其长度⌊t/2⌋的前缀,而右半部分是相同长度的后缀。
注意:每个子字符串的计数与在字符串出现的次数相同。例如,在字符串“ aaa”中,子字符串“ a”出现3次。

例子 :

Input : abba
Output : 6 1 0 0
Explanation : 
"6" 1-palindromes = "a", "b", "b", "a", "bb", "abba".
"1" 2-palindrome = "bb". Because "b" is 1-palindrome 
and "bb" has both left and right parts equal. 
"0" 3-palindrome and 4-palindrome.

Input : abacaba
Output : 12 4 1 0 0 0 0
Explanation : 
"12" 1-palindromes = "a", "b", "a", "c", "a", "b", 
"a", "aba", "aca", "aba", "bacab", "abacaba".
"4" 2-palindromes = "aba", "aca", "aba", "abacaba". 
Because "a" and "aba" are 1-palindromes.
NOTE :  "bacab" is not 2-palindrome as "ba" 
is not 1-palindrome. "1" 3-palindrome = "abacaba". 
Because is "aba" is 2-palindrome. "0" other 
k-pallindromes where 4 < = k < = 7.

方法:取一个字符串s,说它是一个1-回文,然后检查它的左半部分也变成了一个1-回文,那么显然它的右部分将始终等于左部分(因为该字符串也是一个1-回文)回文)将原始字符串设为2回文。现在,类似地,检查字符串的左半部分,它也变成了1回文,然后将左半部分变成了2回文,因此,将原始字符串变成了3回文,依此类推直到仅剩1个字母,或者该部分不是1个回文。
让我们取字符串=“ abacaba”。已知的“算盘”是1-回文。因此,在检查左半部分“ aba”(也是1回文)时,会将“ abacaba”变成2回文。然后,检查“ aba”的左半部分“ a”,它也是1回文。因此,它使“ aba”成为2回文,“ aba”使“ ababaca”成为3回文。因此,换句话说,如果字符串是k回文,那么它也是(k-1)回文,(k-2)回文,依此类推,直到1回文。下面给出了相同的代码,该代码首先检查每个子串(如果它是回文),然后以对数时间递归计算k-回文子串的数目。

下面是上述方法的实现:

C++
// A C++ program which counts different
// palindromic characteristics of a string.
#include 
using namespace std;
  
const int MAX_STR_LEN = 1000;
  
bool P[MAX_STR_LEN][MAX_STR_LEN];
int Kpal[MAX_STR_LEN];
  
// A C++ function which checks whether a
// substring str[i..j] of a given string
// is a palindrome or not.
void checkSubStrPal(string str, int n)
{
  
    // P[i][j] = true if substring str
    // [i..j] is palindrome, else false
    memset(P, false, sizeof(P));
  
    // palindrome of single length
    for (int i = 0; i < n; i++)
        P[i][i] = true;
  
    // palindrome of length 2
    for (int i = 0; i < n - 1; i++)
        if (str[i] == str[i + 1])
            P[i][i + 1] = true;
  
    // Palindromes of length more then 2.
    // This loop is similar to Matrix Chain
    // Multiplication. We start with a gap of
    // length 2 and fill P table in a way that
    // gap between starting and ending indexes
    // increases one by one by outer loop.
    for (int gap = 2; gap < n; gap++)
    {
  
        // Pick starting point for current gap
        for (int i = 0; i < n - gap; i++)
        {
  
            // Set ending point
            int j = gap + i;
  
            // If current string is palindrome
            if (str[i] == str[j] && P[i + 1][j - 1])
                P[i][j] = true;
        }
    }
}
  
// A C++ function which recursively
// counts if a string str [i..j] is
// a k-palindromic string or not.
void countKPalindromes(int i, int j, int k)
{
    // terminating condition for a
    // string which is a k-palindrome.
    if (i == j)
    {
        Kpal[k]++;
        return;
    }
  
    // terminating condition for a
    // string which is not a k-palindrome.
    if (P[i][j] == false)
        return;
  
    // increases the counter for the
    // string if it is a k-palindrome.
    Kpal[k]++;
  
    // mid is middle pointer of
    // the string str [i...j].
    int mid = (i + j) / 2;
  
    // if length of string which is
    // (j - i + 1) is odd than we have
    // to subtract one from mid.
    // else if even then no change.
    if ((j - i + 1) % 2 == 1)
        mid--;
  
    // if the string is k-palindrome
    // then we check if it is a
    // (k+1) - palindrome or not by
    // just sending any of one half of
    // the string to the Count_k_Palindrome
    // function.
    countKPalindromes(i, mid, k + 1);
}
  
void printKPalindromes(string s)
{
  
    // Count of k-palindromes is equal
    // to zero initially.
    memset(Kpal, 0, sizeof(Kpal));
  
    // Finding all palindromic
    // substrings of given string
    int n = s.length();
    checkSubStrPal(s, n);
  
    // counting k-palindromes for each and
    // every substring of given string. .
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - i; j++)
            countKPalindromes(j, j + i, 1);
  
    // Output the number of K-palindromic
    // substrings of a given string.
    for (int i = 1; i <= n; i++)
        cout << Kpal[i] << " ";
    cout << "\n";
}
  
// Driver code
int main()
{
    string s = "abacaba";
    printKPalindromes(s);
    return 0;
}


Java
// Java program which counts 
// different palindromic 
// characteristics of a string.         
import java.io.*;
  
class GFG
{
    static int MAX_STR_LEN = 1000;
      
    static boolean P[][] = 
           new boolean[MAX_STR_LEN][MAX_STR_LEN];
    static int []Kpal = 
           new int[MAX_STR_LEN];
      
    // function which checks 
    // whether a substring 
    // str[i..j] of a given 
    // string is a palindrome or not.
    static void checkSubStrPal(String str, 
                               int n)
    {
      
        // P[i,j] = true if substring 
        // str [i..j] is palindrome, 
        // else false
        for (int i = 0; i < MAX_STR_LEN; i++) 
        {
            for (int j = 0; j < MAX_STR_LEN; j++)
                P[i][j] = false;
            Kpal[i] = 0;
        }
          
        // palindrome of 
        // single length
        for (int i = 0; i < n; i++)
            P[i][i] = true;
      
        // palindrome of 
        // length 2
        for (int i = 0; i < n - 1; i++)
            if (str.charAt(i) == str.charAt(i + 1))
                P[i][i + 1] = true;
      
        // Palindromes of length 
        // more then 2. This loop 
        // is similar to Matrix 
        // Chain Multiplication. 
        // We start with a gap of 
        // length 2 and fill P table 
        // in a way that gap between 
        // starting and ending indexes
        // increases one by one by 
        // outer loop.
        for (int gap = 2; gap < n; gap++)
        {
      
            // Pick starting point
            // for current gap
            for (int i = 0; i < n - gap; i++)
            {
      
                // Set ending point
                int j = gap + i;
      
                // If current string
                // is palindrome
                if (str.charAt(i) == str.charAt(j) && 
                                     P[i + 1][j - 1])
                    P[i][j] = true;
            }
        }
    }
      
    // A function which recursively
    // counts if a string str [i..j] is
    // a k-palindromic string or not.
    static void countKPalindromes(int i, int j, 
                                  int k)
    {
        // terminating condition 
        // for a string which is
        // a k-palindrome.
        if (i == j)
        {
            Kpal[k]++;
            return;
        }
      
        // terminating condition for 
        // a string which is not a 
        // k-palindrome.
        if (P[i][j] == false)
            return;
      
        // increases the counter 
        // for the string if it 
        // is a k-palindrome.
        Kpal[k]++;
      
        // mid is middle pointer of
        // the string str [i...j].
        int mid = (i + j) / 2;
      
        // if length of string which 
        // is (j - i + 1) is odd than
        // we have to subtract one 
        // from mid else if even then 
        // no change.
        if ((j - i + 1) % 2 == 1)
            mid--;
      
        // if the string is k-palindrome
        // then we check if it is a
        // (k+1) - palindrome or not 
        // by just sending any of one 
        // half of the string to the 
        // Count_k_Palindrome function.
        countKPalindromes(i, mid, k + 1);
    }
      
    static void printKPalindromes(String s)
    {
        // Finding all palindromic
        // substrings of given string
        int n = s.length();
        checkSubStrPal(s, n);
      
        // counting k-palindromes for 
        // each and every substring 
        // of given string. .
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n - i; j++)
                countKPalindromes(j, j + i, 1);
      
        // Output the number of 
        // K-palindromic substrings
        // of a given string.
        for (int i = 1; i <= n; i++)
            System.out.print(Kpal[i] + " ");
        System.out.println();
    }
      
    // Driver code
    public static void main(String args[])
    {
        String s = "abacaba";
        printKPalindromes(s);
    }
}
  
// This code is contributd by
// Manish Shaw(manishshaw1)


Python3
# Python program which counts 
# different palindromic 
# characteristics of a string.         
MAX_STR_LEN = 1000;
  
P = [[0 for x in range(MAX_STR_LEN)] 
        for y in range(MAX_STR_LEN)] ;
  
for i in range(0, MAX_STR_LEN) :
    for j in range(0, MAX_STR_LEN) :
        P[i][j] = False;
          
Kpal = [0] * MAX_STR_LEN;
      
# def which checks
# whether a substr[i..j] 
# of a given is a 
# palindrome or not.
def checkSubStrPal(str, n) :
  
    global P, Kpal, MAX_STR_LEN;
              
    # P[i,j] = True if substr
    # [i..j] is palindrome,
    # else False
    for i in range(0, MAX_STR_LEN) :
  
        for j in range(0, MAX_STR_LEN) :
            P[i][j] = False;
        Kpal[i] = 0;
      
    # palindrome of 
    # single length
    for i in range(0, n) :
        P[i][i] = True;
  
    # palindrome of
    # length 2
    for i in range(0, n - 1) :
        if (str[i] == str[i + 1]) :
            P[i][i + 1] = True;
  
    # Palindromes of length more 
    # then 2. This loop is similar 
    # to Matrix Chain Multiplication. 
    # We start with a gap of length 
    # 2 and fill P table in a way 
    # that gap between starting and 
    # ending indexes increases one 
    # by one by outer loop.
    for gap in range(2, n) :
  
        # Pick starting point
        # for current gap
        for i in range(0, n - gap) :
  
            # Set ending point
            j = gap + i;
  
            # If current string
            # is palindrome
            if (str[i] == str[j] and 
                P[i + 1][j - 1]) :
                P[i][j] = True;
  
# A Python def which 
# recursively counts if 
# a str [i..j] is a 
# k-palindromic or not.
def countKPalindromes(i, j, k) :
  
    global Kpal, P;
      
    # terminating condition 
    # for a which is a
    # k-palindrome.
    if (i == j) :
      
        Kpal[k] = Kpal[k] + 1;
        return;
  
    # terminating condition 
    # for a which is not a 
    # k-palindrome.
    if (P[i][j] == False) :
        return;
  
    # increases the counter
    # for the if it is a 
    # k-palindrome.
    Kpal[k] = Kpal[k] + 1;
  
    # mid is middle pointer 
    # of the str [i...j].
    mid = int((i + j) / 2);
  
    # if length of which is
    # (j - i + 1) is odd than 
    # we have to subtract one 
    # from mid else if even 
    # then no change.
    if ((j - i + 1) % 2 == 1) :
        mid = mid - 1;
  
    # if the is k-palindrome
    # then we check if it is a
    # (k+1) - palindrome or not 
    # by just sending any of 
    # one half of the to the 
    # Count_k_Palindrome def.
    countKPalindromes(i, mid, k + 1);
  
def printKPalindromes(s) :
  
    global P, Kpal, MAX_STR_LEN;
              
    # Finding all palindromic
    # substrings of given string
    n = len(s);
    checkSubStrPal(s, n);
  
    # counting k-palindromes 
    # for each and every sub 
    # of given string. .
    for i in range(0, n) :
        for j in range(0, n - i) :
            countKPalindromes(j, j + i, 1);
  
    # Output the number of 
    # K-palindromic substrings
    # of a given string.
    for i in range(1, n + 1) :
        print (Kpal[i], end=" ");
    print();
  
  
# Driver code
s = "abacaba";
printKPalindromes(s);
  
# This code is contributd by
# Manish Shaw(manishshaw1)


C#
// C# program which counts 
// different palindromic 
// characteristics of a string.         
using System;
  
class GFG
{
    static int MAX_STR_LEN = 1000;
      
    static bool [,]P = new bool[MAX_STR_LEN, 
                                MAX_STR_LEN];
    static int []Kpal = new int[MAX_STR_LEN];
      
    // function which checks whether
    // a substring str[i..j] of a 
    // given string is a palindrome or not.
    static void checkSubStrPal(string str, 
                               int n)
    {
      
        // P[i,j] = true if substring str
        // [i..j] is palindrome, else false
        for (int i = 0; i < MAX_STR_LEN; i++) 
        {
            for (int j = 0; j < MAX_STR_LEN; j++)
                P[i, j] = false;
            Kpal[i] = 0;
        }
          
        // palindrome of single length
        for (int i = 0; i < n; i++)
            P[i, i] = true;
      
        // palindrome of length 2
        for (int i = 0; i < n - 1; i++)
            if (str[i] == str[i + 1])
                P[i, i + 1] = true;
      
        // Palindromes of length more 
        // then 2. This loop is similar 
        // to Matrix Chain Multiplication. 
        // We start with a gap of length 2 
        // and fill P table in a way that
        // gap between starting and ending 
        // indexes increases one by one by
        // outer loop.
        for (int gap = 2; gap < n; gap++)
        {
      
            // Pick starting point
            // for current gap
            for (int i = 0; i < n - gap; i++)
            {
      
                // Set ending point
                int j = gap + i;
      
                // If current string
                // is palindrome
                if (str[i] == str[j] && 
                        P[i + 1, j - 1])
                    P[i, j] = true;
            }
        }
    }
      
    // A C++ function which recursively
    // counts if a string str [i..j] is
    // a k-palindromic string or not.
    static void countKPalindromes(int i, int j, 
                                  int k)
    {
        // terminating condition for a
        // string which is a k-palindrome.
        if (i == j)
        {
            Kpal[k]++;
            return;
        }
      
        // terminating condition for 
        // a string which is not a 
        // k-palindrome.
        if (P[i, j] == false)
            return;
      
        // increases the counter for the
        // string if it is a k-palindrome.
        Kpal[k]++;
      
        // mid is middle pointer of
        // the string str [i...j].
        int mid = (i + j) / 2;
      
        // if length of string which is
        // (j - i + 1) is odd than we have
        // to subtract one from mid.
        // else if even then no change.
        if ((j - i + 1) % 2 == 1)
            mid--;
      
        // if the string is k-palindrome
        // then we check if it is a
        // (k+1) - palindrome or not 
        // by just sending any of one 
        // half of the string to the 
        // Count_k_Palindrome function.
        countKPalindromes(i, mid, k + 1);
    }
      
    static void printKPalindromes(string s)
    {
        // Finding all palindromic
        // substrings of given string
        int n = s.Length;
        checkSubStrPal(s, n);
      
        // counting k-palindromes for each and
        // every substring of given string. .
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n - i; j++)
                countKPalindromes(j, j + i, 1);
      
        // Output the number of K-palindromic
        // substrings of a given string.
        for (int i = 1; i <= n; i++)
            Console.Write(Kpal[i] + " ");
        Console.WriteLine();
    }
      
    // Driver code
    static void Main()
    {
        string s = "abacaba";
        printKPalindromes(s);
    }
}
  
// This code is contributd by
// Manish Shaw(manishshaw1)


PHP


输出 :
12 4 1 0 0 0 0

时间复杂度: O( n^2$\log{n}$ )
辅助空间: O( n^2 )