Question Source: http://acm.hdu.edu.cn/showproblem.php? Pid = 1, 1513
Question:
Evaluate how to add a limited number of characters to an existing string to make it a return, and the number of the limited characters is as small as possible.
My incorrect ideas:
At the beginning, I divided the characters into two segments, the second segment in reverse order, and the first section to find the largest public subsequence, using the length of the first and second sections and the two times that of the common subsequence, I divide them into two types based on the given number of characters: odd and even, however, I found that a lot of test data were incorrect results. After that, I divided the results into many situations and found that there were endless error data. I finally gave up and thought that there was a whole error.
After the game, I saw other people's ideas:
Returns the given string (S) in reverse order to (S), and calculates the length of the common subsequences (n) of S and S (len) minus the public sequence length (n ).
Although this idea was flashed in the mind of the game, it was directly rejected by the subconscious. Now let's prove that:
First, if we append S directly to a new string after S, it must be a return string, which is equivalent to a return string formed by appending n characters. But this is no longer the smallest. Even if the given string "S" is "ACBD", it won't be followed by three dead characters, but it can be: ABCDCBA. In fact, S and s' actually have many public parts. Although they are text-back, if they can combine the parts they form into symmetry, then they will add less elements, it is not difficult to find that the positions of the flipped string S and string S are symmetric, and it is not difficult to find the longest common subsequence in combination:
* Z B c a d e * B *** z h (1)
H z B *** e d * a c B z * (2)
Therefore, the number of asterisks in (1) or (2) is the minimum number of elements to be added.
Because the data size of this question is relatively large, the two-dimensional interval DP exceeds the memory given by the question. however, if you are familiar with the longest common subsequence, you will find that the two rows in the two-dimensional interval are used at most in each plan, so you can use these two rows cyclically to improve memory utilization. The following is my code:
# Include <iostream> # include <cstdio> using namespace std; char str1 [5010], str2 [5010]; short dp [2] [5010]; int main () {int n; while (scanf ("% d", & n )! = EOF) {getchar (); int I, j; int len; for (I = 0; I <n; I ++) scanf ("% c ", & str1 [I]); for (I = 0; I <n; I ++) // reverse order. Str2 [n-1-i] = str1 [I]; for (I = 0; I <= n; I ++) // initialization. The first row is all zero, and the first number of the second row is 0; dp [0] [I] = 0; dp [1] [0] = 0; for (I = 0; I <n; I ++) {for (j = 0; j <n; j ++) {if (str1 [I] = str2 [j]) {dp [1] [j + 1] = dp [0] [j] + 1 ;} else {if (dp [0] [j + 1]> dp [1] [j]) dp [1] [j + 1] = dp [0] [j + 1]; elsedp [1] [j + 1] = dp [1] [j];} for (j = 0; j <= n; j ++) // changes the row typed by algorithm to the first row,
<Span style = "white-space: pre"> </span> // you can calculate the next row in the second row. Dp [0] [j] = dp [1] [j]; dp [1] [0] = 0;} printf ("% d \ n ", n-dp [1] [n]);} return 0 ;}
HDU 1513