给定字符串S ,任务是找到将给定字符串S拆分为两个非空回文字符串。
例子:
Input: S = “aaaaa”
Output: 4
Explanation:
Possible Splits: {“a”, “aaaa”}, {“aa”, “aaa”}, {“aaa”, “aa”}, {“aaaa”, “a”}
Input: S = “abacc”
Output: 1
Explanation:
Only possible split is “aba”, “cc”.
天真的方法:天真的方法是在每个可能的索引处分割字符串,并检查两个子字符串是否都是回文。如果是,则增加该索引的计数。打印最终计数。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to check whether the
// substring from l to r is
// palindrome or not
bool isPalindrome(int l, int r,
string& s)
{
while (l <= r) {
// If characters at l and
// r differ
if (s[l] != s[r])
// Not a palindrome
return false;
l++;
r--;
}
// If the string is
// a palindrome
return true;
}
// Function to count and return
// the number of possible splits
int numWays(string& s)
{
int n = s.length();
// Stores the count
// of splits
int ans = 0;
for (int i = 0;
i < n - 1; i++) {
// Check if the two substrings
// after the split are
// palindromic or not
if (isPalindrome(0, i, s)
&& isPalindrome(i + 1,
n - 1, s)) {
// If both are palindromes
ans++;
}
}
// Print the final count
return ans;
}
// Driver Code
int main()
{
string S = "aaaaa";
cout << numWays(S);
return 0;
}
Java
// Java program to implement
// the above approach
class GFG{
// Function to check whether the
// substring from l to r is
// palindrome or not
public static boolean isPalindrome(int l, int r,
String s)
{
while (l <= r)
{
// If characters at l and
// r differ
if (s.charAt(l) != s.charAt(r))
// Not a palindrome
return false;
l++;
r--;
}
// If the string is
// a palindrome
return true;
}
// Function to count and return
// the number of possible splits
public static int numWays(String s)
{
int n = s.length();
// Stores the count
// of splits
int ans = 0;
for(int i = 0; i < n - 1; i++)
{
// Check if the two substrings
// after the split are
// palindromic or not
if (isPalindrome(0, i, s) &&
isPalindrome(i + 1, n - 1, s))
{
// If both are palindromes
ans++;
}
}
// Print the final count
return ans;
}
// Driver Code
public static void main(String args[])
{
String S = "aaaaa";
System.out.println(numWays(S));
}
}
// This code is contributed by SoumikMondal
Python3
# Python3 program to implement
# the above approach
# Function to check whether the
# substring from l to r is
# palindrome or not
def isPalindrome(l, r, s):
while (l <= r):
# If characters at l and
# r differ
if (s[l] != s[r]):
# Not a palindrome
return bool(False)
l += 1
r -= 1
# If the string is
# a palindrome
return bool(True)
# Function to count and return
# the number of possible splits
def numWays(s):
n = len(s)
# Stores the count
# of splits
ans = 0
for i in range(n - 1):
# Check if the two substrings
# after the split are
# palindromic or not
if (isPalindrome(0, i, s) and
isPalindrome(i + 1, n - 1, s)):
# If both are palindromes
ans += 1
# Print the final count
return ans
# Driver Code
S = "aaaaa"
print(numWays(S))
# This code is contributed by divyeshrabadiya07
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Function to check whether the
// substring from l to r is
// palindrome or not
public static bool isPalindrome(int l, int r,
string s)
{
while (l <= r)
{
// If characters at l and
// r differ
if (s[l] != s[r])
// Not a palindrome
return false;
l++;
r--;
}
// If the string is
// a palindrome
return true;
}
// Function to count and return
// the number of possible splits
public static int numWays(string s)
{
int n = s.Length;
// Stores the count
// of splits
int ans = 0;
for(int i = 0; i < n - 1; i++)
{
// Check if the two substrings
// after the split are
// palindromic or not
if (isPalindrome(0, i, s) &&
isPalindrome(i + 1, n - 1, s))
{
// If both are palindromes
ans++;
}
}
// Print the final count
return ans;
}
// Driver Code
public static void Main(string []args)
{
string S = "aaaaa";
Console.Write(numWays(S));
}
}
// This code is contributed by Rutvik
Javascript
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Modulo for rolling hash
const int MOD = 1e9 + 9;
// Small prime for rolling hash
const int P = 37;
// Maximum length of string
const int MAXN = 1e5 + 5;
// Stores prefix hash
vector prefixHash(MAXN);
// Stores suffix hash
vector suffixHash(MAXN);
// Stores inverse modulo
// of P for prefix
vector inversePrefix(MAXN);
// Stores inverse modulo
// of P for suffix
vector inverseSuffix(MAXN);
int n;
int power(int x, int y, int mod)
{
// Function to compute
// power under modulo
if (x == 0)
return 0;
int ans = 1;
while (y > 0) {
if (y & 1)
ans = (1LL * ans * x)
% MOD;
x = (1LL * x * x) % MOD;
y >>= 1;
}
return ans;
}
// Precompte hashes for the
// given string
void preCompute(string& s)
{
int x = 1;
for (int i = 0; i 0)
prefixHash[i]
= (prefixHash[i]
+ prefixHash[i - 1])
% MOD;
// Compute inverse modulo
// of P ^ i for division
// using Fermat Little theorem
inversePrefix[i] = power(x, MOD - 2,
MOD);
x = (1LL * x * P) % MOD;
}
x = 1;
// Calculate suffix hash
for (int i = n - 1; i >= 0; i--) {
// Calculate and store hash
suffixHash[i]
= (1LL * int(s[i]
- 'a' + 1)
* x)
% MOD;
if (i 0
? prefixHash[l - 1]
: 0);
h = (h + MOD) % MOD;
h = (1LL * h * inversePrefix[l])
% MOD;
return h;
}
// Function to return Suffix
// Hash of substring
int getSuffixHash(int l, int r)
{
// Calculate suffix hash
// from l to r
int h = suffixHash[l]
- (r < n - 1
? suffixHash[r + 1]
: 0);
h = (h + MOD) % MOD;
h = (1LL * h * inverseSuffix[r])
% MOD;
return h;
}
int numWays(string& s)
{
n = s.length();
// Compute prefix and
// suffix hashes
preCompute(s);
// Stores the number of
// possible splits
int ans = 0;
for (int i = 0;
i < n - 1; i++) {
int preHash = getPrefixHash(0, i);
int sufHash = getSuffixHash(0, i);
// If the substring s[0]...s[i]
// is not palindromic
if (preHash != sufHash)
continue;
preHash = getPrefixHash(i + 1,
n - 1);
sufHash = getSuffixHash(i + 1,
n - 1);
// If the substring (i + 1, n - 1)
// is not palindromic
if (preHash != sufHash)
continue;
// If both are palindromic
ans++;
}
return ans;
}
// Driver Code
int main()
{
string s = "aaaaa";
int ans = numWays(s);
cout << ans << endl;
return 0;
}
输出:
4
时间复杂度: O(N 2 )
高效的方法:可以使用哈希和Rabin-Karp算法来优化上述方法,以存储字符串的前缀和后缀哈希。请按照以下步骤解决问题:
- 计算给定字符串的前缀和后缀哈希。
- 对于[1,N – 1]范围内的每个索引i,检查两个子字符串[0,i – 1]和[i,N – 1]是否是回文。
- 要检查子字符串[l,r]是否是回文,只需检查:
PrefixHash[l - r] = SuffixHash[l - r]
- 对于发现有两个子字符串回文的每个索引i,增加计数。
- 打印count的最终值。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Modulo for rolling hash
const int MOD = 1e9 + 9;
// Small prime for rolling hash
const int P = 37;
// Maximum length of string
const int MAXN = 1e5 + 5;
// Stores prefix hash
vector prefixHash(MAXN);
// Stores suffix hash
vector suffixHash(MAXN);
// Stores inverse modulo
// of P for prefix
vector inversePrefix(MAXN);
// Stores inverse modulo
// of P for suffix
vector inverseSuffix(MAXN);
int n;
int power(int x, int y, int mod)
{
// Function to compute
// power under modulo
if (x == 0)
return 0;
int ans = 1;
while (y > 0) {
if (y & 1)
ans = (1LL * ans * x)
% MOD;
x = (1LL * x * x) % MOD;
y >>= 1;
}
return ans;
}
// Precompte hashes for the
// given string
void preCompute(string& s)
{
int x = 1;
for (int i = 0; i 0)
prefixHash[i]
= (prefixHash[i]
+ prefixHash[i - 1])
% MOD;
// Compute inverse modulo
// of P ^ i for division
// using Fermat Little theorem
inversePrefix[i] = power(x, MOD - 2,
MOD);
x = (1LL * x * P) % MOD;
}
x = 1;
// Calculate suffix hash
for (int i = n - 1; i >= 0; i--) {
// Calculate and store hash
suffixHash[i]
= (1LL * int(s[i]
- 'a' + 1)
* x)
% MOD;
if (i 0
? prefixHash[l - 1]
: 0);
h = (h + MOD) % MOD;
h = (1LL * h * inversePrefix[l])
% MOD;
return h;
}
// Function to return Suffix
// Hash of substring
int getSuffixHash(int l, int r)
{
// Calculate suffix hash
// from l to r
int h = suffixHash[l]
- (r < n - 1
? suffixHash[r + 1]
: 0);
h = (h + MOD) % MOD;
h = (1LL * h * inverseSuffix[r])
% MOD;
return h;
}
int numWays(string& s)
{
n = s.length();
// Compute prefix and
// suffix hashes
preCompute(s);
// Stores the number of
// possible splits
int ans = 0;
for (int i = 0;
i < n - 1; i++) {
int preHash = getPrefixHash(0, i);
int sufHash = getSuffixHash(0, i);
// If the substring s[0]...s[i]
// is not palindromic
if (preHash != sufHash)
continue;
preHash = getPrefixHash(i + 1,
n - 1);
sufHash = getSuffixHash(i + 1,
n - 1);
// If the substring (i + 1, n - 1)
// is not palindromic
if (preHash != sufHash)
continue;
// If both are palindromic
ans++;
}
return ans;
}
// Driver Code
int main()
{
string s = "aaaaa";
int ans = numWays(s);
cout << ans << endl;
return 0;
}
输出:
4
时间复杂度: O(N * log(10 9 ))
空间复杂度: O(N)