给定一个字符串S ,任务是找到在子字符串S1, S2, S3, …, Sk 中划分/划分给定字符串的方法数量,使得S1 < S2 < S3 < … < Sk (按字典顺序)。
例子:
Input: S = “aabc”
Output: 6
Following are the allowed partitions:
{“aabc”}, {“aa”, “bc”}, {“aab”, “c”}, {“a”, “abc”},
{“a, “ab”, “c”} and {“aa”, “b”, “c”}.
Input: S = “za”
Output: 1
Only possible partition is {“za”}.
方法:这个问题可以用动态规划解决。
- 将DP[i][j]定义为划分子串S[0…j] 的方法数,使得S[i, j]是最后一个分区。
- 现在,递归关系将是DP[i][j] = (DP[k][i – 1])对于所有k ≥ 0和i ≤ N – 1 的总和,其中N是字符串的长度。
- 最终答案将是(DP[i][N – 1])对于0到N – 1之间的所有i的总和,因为这些子字符串将成为某些可能的分区方式中的最后一个分区。
- 所以,这里对于所有子串S[i][j] ,找到子串S[k][i – 1]使得S[k][i – 1]在字典上小于S[i] [j]并将DP[k][i – 1] 添加到DP[i][j] 。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the number of
// ways of partioning
int ways(string s, int n)
{
int dp[n][n];
// Initialize DP table
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
dp[i][j] = 0;
}
// Base Case
for (int i = 0; i < n; i++)
dp[0][i] = 1;
for (int i = 1; i < n; i++) {
// To store sub-string S[i][j]
string temp;
for (int j = i; j < n; j++) {
temp += s[j];
// To store sub-string S[k][i-1]
string test;
for (int k = i - 1; k >= 0; k--) {
test += s[k];
if (test < temp) {
dp[i][j] += dp[k][i - 1];
}
}
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
// Add all the ways where S[i][n-1]
// will be the last partition
ans += dp[i][n - 1];
}
return ans;
}
// Driver code
int main()
{
string s = "aabc";
int n = s.length();
cout << ways(s, n);
return 0;
}
Java
// Java implementation of the above approach
class GFG
{
// Function to return the number of
// ways of partioning
static int ways(String s, int n)
{
int dp[][] = new int[n][n];
// Initialize DP table
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
dp[i][j] = 0;
}
// Base Case
for (int i = 0; i < n; i++)
dp[0][i] = 1;
for (int i = 1; i < n; i++)
{
// To store sub-string S[i][j]
String temp = "";
for (int j = i; j < n; j++)
{
temp += s.charAt(j);
// To store sub-string S[k][i-1]
String test = "";
for (int k = i - 1; k >= 0; k--)
{
test += s.charAt(k);
if (test.compareTo(temp) < 0)
{
dp[i][j] += dp[k][i - 1];
}
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
{
// Add all the ways where S[i][n-1]
// will be the last partition
ans += dp[i][n - 1];
}
return ans;
}
// Driver code
public static void main (String[] args)
{
String s = "aabc";
int n = s.length();
System.out.println(ways(s, n));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation of the approach
# Function to return the number of
# ways of partioning
def ways(s, n):
dp = [[0 for i in range(n)]
for i in range(n)]
# Base Case
for i in range(n):
dp[0][i] = 1
for i in range(1, n):
# To store sub-S[i][j]
temp = ""
for j in range(i, n):
temp += s[j]
# To store sub-S[k][i-1]
test = ""
for k in range(i - 1, -1, -1):
test += s[k]
if (test < temp):
dp[i][j] += dp[k][i - 1]
ans = 0
for i in range(n):
# Add all the ways where S[i][n-1]
# will be the last partition
ans += dp[i][n - 1]
return ans
# Driver code
s = "aabc"
n = len(s)
print(ways(s, n))
# This code is contributed by Mohit Kumarv
C#
// C# implementation of the above approach
using System;
class GFG
{
// Function to return the number of
// ways of partioning
static int ways(String s, int n)
{
int [,]dp = new int[n, n];
// Initialize DP table
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
dp[i, j] = 0;
}
// Base Case
for (int i = 0; i < n; i++)
dp[0, i] = 1;
for (int i = 1; i < n; i++)
{
// To store sub-string S[i,j]
String temp = "";
for (int j = i; j < n; j++)
{
temp += s[j];
// To store sub-string S[k,i-1]
String test = "";
for (int k = i - 1; k >= 0; k--)
{
test += s[k];
if (test.CompareTo(temp) < 0)
{
dp[i, j] += dp[k, i - 1];
}
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
{
// Add all the ways where S[i,n-1]
// will be the last partition
ans += dp[i, n - 1];
}
return ans;
}
// Driver code
public static void Main (String[] args)
{
String s = "aabc";
int n = s.Length;
Console.WriteLine(ways(s, n));
}
}
// This code is contributed by PrinciRaj1992
Javascript
输出:
6
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。