形成回文的最小插入数| DP-28

给定字符串 str ,任务是找到要插入的最小字符数,以将其转换为回文。

null

在我们继续之前,让我们通过几个例子来理解:

  • ab: 所需的插入次数为1,即。 B ab
  • aa: 所需插入次数为0,即aa
  • abcd: 所需插入次数为3次,即。 dcb abcd
  • abcda: 所需的插入次数为2次,即a dc bcda与子字符串bcd中的插入数相同(为什么?)。
  • abcde: 所需插入次数为4次,即。 edcb 憎恶

让输入字符串 str[l……h] .问题可分为三个部分:

  1. 找到子串str[l+1,…..h]中插入的最小数目。
  2. 在子字符串str[l…….h-1]中找到插入的最小数目。
  3. 找到子字符串str[l+1……h-1]中插入的最小数目。

递归方法 :字符串中插入的最小数目 str[l….h] 可给出如下公式:

  • 如果str[l]等于str[h],则为minInsertions(str[l+1..h-1])
  • min(MininSections(str[l…..h-1]),MininSections(str[l+1…..h]))+1,否则

以下是上述方法的实施情况:

C++

// A Naive recursive program to find minimum
// number insertions needed to make a string
// palindrome
#include<bits/stdc++.h>
using namespace std;
// Recursive function to find
// minimum number of insertions
int findMinInsertions( char str[], int l, int h)
{
// Base Cases
if (l > h) return INT_MAX;
if (l == h) return 0;
if (l == h - 1) return (str[l] == str[h])? 0 : 1;
// Check if the first and last characters are
// same. On the basis of the comparison result,
// decide which subproblem(s) to call
return (str[l] == str[h])?
findMinInsertions(str, l + 1, h - 1):
(min(findMinInsertions(str, l, h - 1),
findMinInsertions(str, l + 1, h)) + 1);
}
// Driver code
int main()
{
char str[] = "geeks" ;
cout << findMinInsertions(str, 0, strlen (str) - 1);
return 0;
}
// This code is contributed by
// Akanksha Rai


C

// A Naive recursive program to find minimum
// number insertions needed to make a string
// palindrome
#include <stdio.h>
#include <limits.h>
#include <string.h>
// A utility function to find minimum of two numbers
int min( int a, int b)
{ return a < b ? a : b; }
// Recursive function to find minimum number of
// insertions
int findMinInsertions( char str[], int l, int h)
{
// Base Cases
if (l > h) return INT_MAX;
if (l == h) return 0;
if (l == h - 1) return (str[l] == str[h])? 0 : 1;
// Check if the first and last characters are
// same. On the basis of the comparison result,
// decide which subproblem(s) to call
return (str[l] == str[h])?
findMinInsertions(str, l + 1, h - 1):
(min(findMinInsertions(str, l, h - 1),
findMinInsertions(str, l + 1, h)) + 1);
}
// Driver program to test above functions
int main()
{
char str[] = "geeks" ;
printf ( "%d" , findMinInsertions(str, 0, strlen (str)-1));
return 0;
}


JAVA

// A Naive recursive Java program to find minimum
// number insertions needed to make a string
// palindrome
class GFG {
// Recursive function to find minimum number
// of insertions
static int findMinInsertions( char str[], int l,
int h)
{
// Base Cases
if (l > h) return Integer.MAX_VALUE;
if (l == h) return 0 ;
if (l == h - 1 ) return (str[l] == str[h])? 0 : 1 ;
// Check if the first and last characters
// are same. On the basis of the  comparison
// result, decide which subproblem(s) to call
return (str[l] == str[h])?
findMinInsertions(str, l + 1 , h - 1 ):
(Integer.min(findMinInsertions(str, l, h - 1 ),
findMinInsertions(str, l + 1 , h)) + 1 );
}
// Driver program to test above functions
public static void main(String args[])
{
String str= "geeks" ;
System.out.println(findMinInsertions(str.toCharArray(),
0 , str.length()- 1 ));
}
}
// This code is contributed by Sumit Ghosh


Python 3

# A Naive recursive program to find minimum
# number insertions needed to make a string
# palindrome
import sys
# Recursive function to find minimum
# number of insertions
def findMinInsertions( str , l, h):
# Base Cases
if (l > h):
return sys.maxsize
if (l = = h):
return 0
if (l = = h - 1 ):
return 0 if ( str [l] = = str [h]) else 1
# Check if the first and last characters are
# same. On the basis of the comparison result,
# decide which subproblem(s) to call
if ( str [l] = = str [h]):
return findMinInsertions( str , l + 1 , h - 1 )
else :
return ( min (findMinInsertions( str , l, h - 1 ),
findMinInsertions( str , l + 1 , h)) + 1 )
# Driver Code
if __name__ = = "__main__" :
str = "geeks"
print (findMinInsertions( str , 0 , len ( str ) - 1 ))
# This code is contributed by ita_c


C#

// A Naive recursive C# program
// to find minimum number
// insertions needed to make
// a string palindrome
using System;
class GFG
{
// Recursive function to
// find minimum number of
// insertions
static int findMinInsertions( char []str,
int l, int h)
{
// Base Cases
if (l > h) return int .MaxValue;
if (l == h) return 0;
if (l == h - 1)
return (str[l] == str[h])? 0 : 1;
// Check if the first and
// last characters are same.
// On the basis of the
// comparison result, decide
// which subproblem(s) to call
return (str[l] == str[h])?
findMinInsertions(str,
l + 1, h - 1):
(Math.Min(findMinInsertions(str, l,
h - 1),
findMinInsertions(str, l +
1, h)) + 1);
}
// Driver Code
public static void Main()
{
string str= "geeks" ;
Console.WriteLine(findMinInsertions(str.ToCharArray(),
0, str.Length - 1));
}
}
// This code is contributed by Sam007


Javascript

<script>
// A Naive recursive JavaScript program to find minimum
// number insertions needed to make a string
// palindrome
// Recursive function to find minimum number
// of insertions
function findMinInsertions(str,l,h)
{
// Base Cases
if (l > h)
return Number.MAX_VALUE;
if (l == h)
return 0;
if (l == h - 1)
return (str[l] == str[h])? 0 : 1;
// Check if the first and last characters
// are same. On the basis of the  comparison
// result, decide which subproblem(s) to call
return (str[l] == str[h]) ?
findMinInsertions(str, l + 1, h - 1) :
(Math.min(findMinInsertions(str, l, h - 1),
findMinInsertions(str, l + 1, h)) + 1)
}
// Driver program to test above functions
let str= "geeks" ;
document.write(findMinInsertions(str,0, str.length-1));
// This code is contributed by rag2127
</script>


输出:

3

基于动态规划的求解 如果我们仔细观察上述方法,我们会发现它 重叠子问题 . 假设我们想在字符串“abcde”中找到最小插入次数:

                      abcde            /       |                 /        |                   bcde         abcd       bcd  <- case 3 is discarded as str[l] != str[h]       /   |          /   |         /    |         /    |         cde   bcd  cd   bcd abc bc   / |   / |  /| / | de cd d cd bc c………………….

粗体的子字符串表示递归将被终止,递归树不能从那里开始。相同颜色的子字符串表示 重叠子问题 .

如何重用子问题的解决方案? 记忆技术用于避免类似的子问题回忆。我们可以创建一个表来存储子问题的结果,以便在再次遇到相同的子问题时可以直接使用它们。 下表表示字符串abcde的存储值。

a b c d e----------0 1 2 3 40 0 1 2 3 0 0 0 1 2 0 0 0 0 1 0 0 0 0 0

怎么填桌子? 这张桌子应该以对角线的方式填满。对于字符串abcde,0…4,应按以下顺序填写表格:

Gap = 1: (0, 1) (1, 2) (2, 3) (3, 4)Gap = 2: (0, 2) (1, 3) (2, 4)Gap = 3: (0, 3) (1, 4)Gap = 4: (0, 4)

以下是上述方法的实施情况:

C++

// A Dynamic Programming based program to find
// minimum number insertions needed to make a
// string palindrome
#include <bits/stdc++.h>
using namespace std;
// A DP function to find minimum
// number of insertions
int findMinInsertionsDP( char str[], int n)
{
// Create a table of size n*n. table[i][j]
// will store minimum number of insertions
// needed to convert str[i..j] to a palindrome.
int table[n][n], l, h, gap;
// Initialize all table entries as 0
memset (table, 0, sizeof (table));
// Fill the table
for (gap = 1; gap < n; ++gap)
for (l = 0, h = gap; h < n; ++l, ++h)
table[l][h] = (str[l] == str[h])?
table[l + 1][h - 1] :
(min(table[l][h - 1],
table[l + 1][h]) + 1);
// Return minimum number of insertions
// for str[0..n-1]
return table[0][n - 1];
}
// Driver Code
int main()
{
char str[] = "geeks" ;
cout << findMinInsertionsDP(str, strlen (str));
return 0;
}
// This is code is contributed by rathbhupendra


C

// A Dynamic Programming based program to find
// minimum number insertions needed to make a
// string palindrome
#include <stdio.h>
#include <string.h>
// A utility function to find minimum of two integers
int min( int a, int b)
{ return a < b ? a : b;  }
// A DP function to find minimum number of insertions
int findMinInsertionsDP( char str[], int n)
{
// Create a table of size n*n. table[i][j]
// will store minimum number of insertions
// needed to convert str[i..j] to a palindrome.
int table[n][n], l, h, gap;
// Initialize all table entries as 0
memset (table, 0, sizeof (table));
// Fill the table
for (gap = 1; gap < n; ++gap)
for (l = 0, h = gap; h < n; ++l, ++h)
table[l][h] = (str[l] == str[h])?
table[l+1][h-1] :
(min(table[l][h-1],
table[l+1][h]) + 1);
// Return minimum number of insertions for
// str[0..n-1]
return table[0][n-1];
}
// Driver program to test above function.
int main()
{
char str[] = "geeks" ;
printf ( "%d" , findMinInsertionsDP(str, strlen (str)));
return 0;
}


JAVA

// A Java solution for Dynamic Programming
// based program to find minimum number
// insertions needed to make a string
// palindrome
import java.util.Arrays;
class GFG
{
// A DP function to find minimum number
// of insertions
static int findMinInsertionsDP( char str[], int n)
{
// Create a table of size n*n. table[i][j]
// will store minimum number of insertions
// needed to convert str[i..j] to a palindrome.
int table[][] = new int [n][n];
int l, h, gap;
// Fill the table
for (gap = 1 ; gap < n; ++gap)
for (l = 0 , h = gap; h < n; ++l, ++h)
table[l][h] = (str[l] == str[h])?
table[l+ 1 ][h- 1 ] :
(Integer.min(table[l][h- 1 ],
table[l+ 1 ][h]) + 1 );
// Return minimum number of insertions
// for str[0..n-1]
return table[ 0 ][n- 1 ];
}
// Driver program to test above function.
public static void main(String args[])
{
String str = "geeks" ;
System.out.println(
findMinInsertionsDP(str.toCharArray(), str.length()));
}
}
// This code is contributed by Sumit Ghosh


Python3

# A Dynamic Programming based program to
# find minimum number insertions needed
# to make a string palindrome
# A utility function to find minimum
# of two integers
def Min (a, b):
return min (a, b)
# A DP function to find minimum number
# of insertions
def findMinInsertionsDP(str1, n):
# Create a table of size n*n. table[i][j]
# will store minimum number of insertions
# needed to convert str1[i..j] to a palindrome.
table = [[ 0 for i in range (n)]
for i in range (n)]
l, h, gap = 0 , 0 , 0
# Fill the table
for gap in range ( 1 , n):
l = 0
for h in range (gap, n):
if str1[l] = = str1[h]:
table[l][h] = table[l + 1 ][h - 1 ]
else :
table[l][h] = ( Min (table[l][h - 1 ],
table[l + 1 ][h]) + 1 )
l + = 1
# Return minimum number of insertions
# for str1[0..n-1]
return table[ 0 ][n - 1 ];
# Driver Code
str1 = "geeks"
print (findMinInsertionsDP(str1, len (str1)))
# This code is contributed by
# Mohit kumar 29


C#

// A C# solution for Dynamic Programming
// based program to find minimum number
// insertions needed to make a string
// palindrome
using System;
class GFG
{
// A DP function to find minimum number
// of insertions
static int findMinInsertionsDP( char []str, int n)
{
// Create a table of size n*n. table[i][j]
// will store minimum number of insertions
// needed to convert str[i..j] to a palindrome.
int [,]table = new int [n, n];
int l, h, gap;
// Fill the table
for (gap = 1; gap < n; ++gap)
for (l = 0, h = gap; h < n; ++l, ++h)
table[l, h] = (str[l] == str[h])?
table[l+1, h-1] :
(Math.Min(table[l, h-1],
table[l+1, h]) + 1);
// Return minimum number of insertions
// for str[0..n-1]
return table[0, n-1];
}
// Driver code
public static void Main()
{
String str = "geeks" ;
Console.Write(
findMinInsertionsDP(str.ToCharArray(), str.Length));
}
}
// This code is contributed by Rajput-Ji


Javascript

<script>
// A Javascript solution for Dynamic Programming
// based program to find minimum number
// insertions needed to make a string
// palindrome
// A DP function to find minimum number
// of insertions
function findMinInsertionsDP(str,n)
{
// Create a table of size n*n. table[i][j]
// will store minimum number of insertions
// needed to convert str[i..j] to a palindrome.
let table= new Array(n);
for (let i=0;i<n;i++)
{
table[i]= new Array(n);
}
for (let i=0;i<n;i++)
{
for (let j=0;j<n;j++)
{
table[i][j]=0;
}
}
let  l=0, h=0, gap=0;
// Fill the table
for (gap = 1; gap < n; gap++)
{
for (l = 0, h = gap; h < n; l++, h++)
{
table[l][h] = (str[l] == str[h]) ? table[l+1][h-1] : (Math.min(table[l][h-1],table[l+1][h]) + 1);
}
}
// Return minimum number of insertions
// for str[0..n-1]
return table[0][n - 1];
}
// Driver program to test above function.
let str = "geeks" ;
document.write(findMinInsertionsDP(str, str.length));
// This code is contributed by avanitrachhadiya2155
</script>


输出:

3

时间复杂性: O(N^2) 辅助空间: O(N^2)

另一个动态规划解决方案(变量 最长公共子序列问题) 寻找最小插入的问题也可以通过使用 最长公共子序列(LCS)问题 .如果我们找出字符串及其反面的LCS,我们就知道一个回文最多可以包含多少个字符。我们需要插入剩下的字符。以下是步骤。

  1. 查找输入字符串的LCS长度及其倒数。让长度为“l”。
  2. 所需的最小插入次数是输入字符串的长度减去“l”。

以下是上述方法的实施情况:

C++

// An LCS based program to find minimum number
// insertions needed to make a string palindrome
#include <bits/stdc++.h>
using namespace std;
// Returns length of LCS for X[0..m-1], Y[0..n-1].
int lcs( string X, string Y, int m, int n )
{
int L[m+1][n+1];
int i, j;
/* Following steps build L[m+1][n+1] in bottom
up fashion. Note that L[i][j] contains length
of LCS of X[0..i-1] and Y[0..j-1] */
for (i = 0; i <= m; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;
else if (X[i - 1] == Y[j - 1])
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = max(L[i - 1][j], L[i][j - 1]);
}
}
/* L[m][n] contains length of LCS for X[0..n-1]
and Y[0..m-1] */
return L[m][n];
}
void reverseStr(string& str)
{
int n = str.length();
// Swap character starting from two
// corners
for ( int i = 0; i < n / 2; i++)
swap(str[i], str[n - i - 1]);
}
// LCS based function to find minimum number of
// insertions
int findMinInsertionsLCS(string str, int n)
{
// Creata another string to store reverse of 'str'
string rev = "" ;
rev = str;
reverseStr(rev);
// The output is length of string minus length of lcs of
// str and it reverse
return (n - lcs(str, rev, n, n));
}
// Driver code
int main()
{
string str = "geeks" ;
cout << findMinInsertionsLCS(str, str.length());
return 0;
}
// This code is contributed by rathbhupendra


C

// An LCS based program to find minimum number
// insertions needed to make a string palindrome
#include<stdio.h>
#include <string.h>
/* Utility function to get max of 2 integers */
int max( int a, int b)
{ return (a > b)? a : b; }
/* Returns length of LCS for X[0..m-1], Y[0..n-1].
See http://goo.gl/bHQVP for details of this
function */
int lcs( char *X, char *Y, int m, int n )
{
int L[m+1][n+1];
int i, j;
/* Following steps build L[m+1][n+1] in bottom
up fashion. Note that L[i][j] contains length
of LCS of X[0..i-1] and Y[0..j-1] */
for (i=0; i<=m; i++)
{
for (j=0; j<=n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;
else if (X[i-1] == Y[j-1])
L[i][j] = L[i-1][j-1] + 1;
else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}
/* L[m][n] contains length of LCS for X[0..n-1]
and Y[0..m-1] */
return L[m][n];
}
// LCS based function to find minimum number of
// insertions
int findMinInsertionsLCS( char str[], int n)
{
// Creata another string to store reverse of 'str'
char rev[n+1];
strcpy (rev, str);
strrev(rev);
// The output is length of string minus length of lcs of
// str and it reverse
return (n - lcs(str, rev, n, n));
}
// Driver program to test above functions
int main()
{
char str[] = "geeks" ;
printf ( "%d" , findMinInsertionsLCS(str, strlen (str)));
return 0;
}


JAVA

// An LCS based Java program to find minimum
// number insertions needed to make a string
// palindrome
class GFG
{
/* Returns length of LCS for X[0..m-1],
Y[0..n-1]. See http://goo.gl/bHQVP for
details of this function */
static int lcs( String X, String Y, int m, int n )
{
int L[][] = new int [m+ 1 ][n+ 1 ];
int i, j;
/* Following steps build L[m+1][n+1] in
bottom up fashion. Note that L[i][j]
contains length of LCS of X[0..i-1]
and Y[0..j-1] */
for (i= 0 ; i<=m; i++)
{
for (j= 0 ; j<=n; j++)
{
if (i == 0 || j == 0 )
L[i][j] = 0 ;
else if (X.charAt(i- 1 ) == Y.charAt(j- 1 ))
L[i][j] = L[i- 1 ][j- 1 ] + 1 ;
else
L[i][j] = Integer.max(L[i- 1 ][j], L[i][j- 1 ]);
}
}
/* L[m][n] contains length of LCS for
X[0..n-1] and Y[0..m-1] */
return L[m][n];
}
// LCS based function to find minimum number
// of insertions
static int findMinInsertionsLCS(String str, int n)
{
// Using StringBuffer to reverse a String
StringBuffer sb = new StringBuffer(str);
sb.reverse();
String revString = sb.toString();
// The output is length of string minus
// length of lcs of str and it reverse
return (n - lcs(str, revString , n, n));
}
// Driver program to test above functions
public static void main(String args[])
{
String str = "geeks" ;
System.out.println(
findMinInsertionsLCS(str, str.length()));
}
}
// This code is contributed by Sumit Ghosh


Python3

# An LCS based Python3 program to find minimum
# number insertions needed to make a string
# palindrome
""" Returns length of LCS for X[0..m-1],
Y[0..n-1]. See http://goo.gl/bHQVP for
details of this function """
def lcs(X, Y, m, n) :
L = [[ 0 for i in range (n + 1 )] for j in range (m + 1 )]
""" Following steps build L[m + 1, n + 1] in
bottom up fashion. Note that L[i, j]
contains length of LCS of X[0..i - 1]
and Y[0..j - 1] """
for i in range (m + 1 ) :
for j in range (n + 1 ) :
if (i = = 0 or j = = 0 ) :
L[i][j] = 0
elif (X[i - 1 ] = = Y[j - 1 ]) :
L[i][j] = L[i - 1 ][j - 1 ] + 1
else :
L[i][j] = max (L[i - 1 ][j], L[i][j - 1 ])
""" L[m,n] contains length of LCS for
X[0..n-1] and Y[0..m-1] """
return L[m][n]
# LCS based function to find minimum number
# of insertions
def findMinInsertionsLCS( Str , n) :
# Using charArray to reverse a String
charArray = list ( Str )
charArray.reverse()
revString = "".join(charArray)
# The output is length of string minus
# length of lcs of str and it reverse
return (n - lcs( Str , revString , n, n))
# Driver code
Str = "geeks"
print (findMinInsertionsLCS( Str , len ( Str )))
# This code is contributed by divyehrabadiya07


C#

// An LCS based C# program to find minimum
// number insertions needed to make a string
// palindrome
using System;
class GFG
{
/* Returns length of LCS for X[0..m-1],
Y[0..n-1]. See http://goo.gl/bHQVP for
details of this function */
static int lcs( string X, string Y, int m, int n )
{
int [,] L = new int [m + 1, n + 1];
int i, j;
/* Following steps build L[m+1,n+1] in
bottom up fashion. Note that L[i,j]
contains length of LCS of X[0..i-1]
and Y[0..j-1] */
for (i = 0; i <= m; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0 || j == 0)
L[i, j] = 0;
else if (X[i - 1] == Y[j - 1])
L[i, j] = L[i - 1, j - 1] + 1;
else
L[i, j] = Math.Max(L[i - 1, j], L[i, j - 1]);
}
}
/* L[m,n] contains length of LCS for
X[0..n-1] and Y[0..m-1] */
return L[m,n];
}
// LCS based function to find minimum number
// of insertions
static int findMinInsertionsLCS( string str, int n)
{
// Using charArray to reverse a String
char [] charArray = str.ToCharArray();
Array.Reverse(charArray);
string revString = new string (charArray);
// The output is length of string minus
// length of lcs of str and it reverse
return (n - lcs(str, revString , n, n));
}
// Driver code
static void Main()
{
string str = "geeks" ;
Console.WriteLine(findMinInsertionsLCS(str,str.Length));
}
}
// This code is contributed by mits


Javascript

<script>
// An LCS based Javascript program to find minimum
// number insertions needed to make a string
// palindrome
/* Returns length of LCS for X[0..m-1],
Y[0..n-1]. See http://goo.gl/bHQVP for
details of this function */
function lcs(X, Y, m, n)
{
let L = new Array(m+1);
for (let i = 0; i < m + 1; i++)
{
L[i] = new Array(n+1);
for (let j = 0; j < n + 1; j++)
{
L[i][j] = 0;
}
}
let i, j;
/* Following steps build L[m+1][n+1] in
bottom up fashion. Note that L[i][j]
contains length of LCS of X[0..i-1]
and Y[0..j-1] */
for (i = 0; i <= m; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;
else if (X[i - 1] == Y[j - 1])
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = Math.max(L[i - 1][j], L[i][j - 1]);
}
}
/* L[m][n] contains length of LCS for
X[0..n-1] and Y[0..m-1] */
return L[m][n];
}
// LCS based function to find minimum number
// of insertions
function findMinInsertionsLCS(str, n)
{
let revString = str.split( '' ).reverse().join( '' );
// The output is length of string minus
// length of lcs of str and it reverse
return (n - lcs(str, revString , n, n));
}
// Driver program to test above functions
let str = "geeks" ;
document.write(findMinInsertionsLCS(str, str.length));
// This code is contributed by unknown2108
</script>


输出:

3

时间复杂性: O(N^2) 辅助空间 :O(N^2)

相关文章: 使字符串回文化所需的最小追加数 本文由 阿希什·巴恩瓦尔 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享