If a string is specified, at least a few characters can be inserted to make it a return string.
Question: three methods are summarized as follows.
Method 1:
S1 is the original string, and S2 is copied from right to left by S1.
DP [I] [J] indicates that the string on the left of S1 [I] and S2 [J] is equal to the minimum number of characters to be inserted.
1. When S1 [I]! = S2 [J,
For example:
Substr1:... S1 [I-1]
Substr2:... S2 [J]
Substr1 = substr2
If DP [I] [J] is required, a character equal to S1 [I] must be added to the right of S2 [J], that is
Substr1:... S1 [I-1], S1 [I]
Substr2:... S2 [J], S1 '[I]
Then DP [I] [J] = DP [I-1] [J] + 1
Likewise, DP [I] [J] = DP [I] [J-1] + 1;
Then DP [I] [J] = min (DP [I-1] [J] + 1, DP [I] [J-1] + 1 );
2. When S1 [I] = S2 [J,
For example:
Substr1: · S1 [I-1]
Substr2:... S2 [J-1]
Substr1 = substr2
DP [I] [J] = DP [I-1] [J-1]
Note:
1: Because S2 is replicated from right to left by S1, it is based on symmetry. The answer should be DP [Len] [Len]/2. (I tried to find DP [Len/2] [Len/2], but some details were not taken into consideration. I always gave up wrong. Please reply if you know .)
2. During initialization, note that DP [I] [0] = DP [0] [I] = I. The principle is very simple. If S1's I character is exactly the same as S2's 0th character on the left, you need to add S1 [1] on the left of S2. s1 [2] · S1 [I].
#include <iostream>using namespace std;#define N 5005short dp[N][N];char s1[N], s2[N];int min ( int a, int b ){return a < b ? a : b;}int main(){int len, i, j;while ( scanf("%d",&len) != EOF ){scanf("%s",s1+1);i = 1; j = len;while ( i <= len && j >= 1 ){s2[i] = s1[j];i++; j--;}for ( i = 0; i <= len; i++ )dp[i][0] = dp[0][i] = i;for ( i = 1; i <= len; i++ ){for ( j = 1; j <= len; j++ ){if ( s1[i] == s2[j] )dp[i][j] = dp[i-1][j-1];elsedp[i][j] = min ( dp[i-1][j] + 1, dp[i][j-1] + 1 );}}printf("%d\n", dp[len][len] / 2 );}return 0;}
Method 2:
Returns the largest common subsequence.
It is known that S1, S2, and the same S2 are copied from right to left by S1.
S1 [1], S1 [2], · S1 [I] ·
S2 [1], S2 [2],... · S2 [J], ····
To make S1 = S2, every time we encounter S1 [I]! = S2 [J]: Add a S2 '[J] to S1, add a S1' [I] character to S2, and change it:
S1 [1], S1 [2], · S1 [I] · S2 '[J] ·
S2 [1], S2 [2], · S1 '[I] · S2 [J] ·
In the end, S1 = S2 is obtained, that is, the input string. In this case, the number of characters added to S1 is exactly the same as that of S1 [I]! = Logarithm of S2 [J. That is, the number of characters added = len-length of common subsequences. Therefore, the longest common subsequence is required.
#include <iostream>using namespace std;#define N 5005short dp[N][N];char s1[N], s2[N];int max ( int a, int b ){return a > b ? a : b;}int main(){int len, i, j;//freopen("a.txt","r",stdin);while ( scanf("%d",&len) != EOF ){scanf("%s",s1+1);i = 1; j = len;while ( i <= len && j >= 1 ){s2[i] = s1[j];i++; j--;}for ( i = 1; i <= len; i++ )dp[i][0] = dp[0][i] = 0;for ( i = 1; i <= len; i++ ){for ( j = 1; j <= len; j++ ){if ( s1[i] == s2[j] )dp[i][j] = dp[i-1][j-1] + 1;elsedp[i][j] = max ( dp[i-1][j], dp[i][j-1] );}}if ( dp[len][len] == 0 ) dp[len][len] = 1;printf("%d\n", len - dp[len][len] );}return 0;}
Method 3:
Set S [1] .. s [N] indicates a string of 1 to n bits. If I is the left cursor and J is the right cursor, I decreases from Len and J increments from I + 1. The result is that the rightmost part is changed to a text string, and the text string is gradually increased to the left.
DP [I] [J] indicates the minimum number of characters to be inserted between I and j to form a local retrieval string. The value is set to 0 at first, the final value we need is DP [1] [N]. Then:
If (s [I] = s [J]) // if the two cursors refer to the same character, narrow the range to the center.
DP [I] [J] = DP [I + 1] [J-1];
Else
DP [I] [J] = 1 + min (DP [I + 1] [J], DP [I] [J-1])
The following code optimizes the memory with a rolling array.
#include <iostream>using namespace std;#define N 5005short dp[2][N];char s[N];int min ( int a, int b ){return a < b ? a : b;}int main(){int len,i,j;//freopen("a.txt","r",stdin);while ( scanf("%d",&len) != EOF ){scanf("%s",s+1);memset(dp,0,sizeof(dp));for ( i = len; i >= 1; i-- ){for ( j = i+1; j <= len; j++ ){if ( s[i] == s[j] )dp[i%2][j] = dp[(i+1)%2][j-1];elsedp[i%2][j] = min ( dp[i%2][j-1], dp[(i+1)%2][j] ) + 1;}}printf ( "%d\n",dp[1][len]);}return 0;}