Palindrome
Time Limit: 3000 MS Memory Limit: 65536 K
Total Submissions: 48269 Accepted: 16570
Description
A palindrome is a regular rical string, that is, a string read identically from left to right as well as from right to left. you are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "adb3me "). however, inserting fewer than 2 characters does not produce a palindrome.
Input
Your program is to read from standard input. the first line contains one integer: the length of the input string N, 3 <=n <= 5000. the second line contains one string with length N. the string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'A' to 'Z' and digits from '0' to '9 '. uppercase and lowercase letters are to be considered distinct.
Output
Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.
Sample Input
5
Ab3bdSample Output
2 Source
IOI 2000
Question:
For a string of characters, ask the minimum number of characters that can be added to the string.
(Return string = the string is the same as the string from left to right)
Analysis:
Assume that dp [I] [j] indicates that the string a [I.. j] is changed to palindrome.
At least dp [I] [j] operations (I <= j) are required)
So
If a [I] = a [j], then dp [I] [j] = dp [I + 1] [J-1]
Otherwise, it is dp [I] [j] = min (dp [I-1] [j], dp [I] [J-1]) + 1 This is because we need to add a number before or after it.
Initialize to dp [I] [I] = 0, dp [I] [I + 1] = a [I] = a [I + 1]? 0: 1
Two methods:
Recursion:
Int getdp (int I, int j ){
If (I = j) return 0;
If (I = j-1) return a [I] = a [I + 1]? 0: 2
If (dp [I] [j]! =-1) return dp [I] [j]
If (a [I] = a [j]) return dp [I] [j] = getdp (I + 1, J-1)
Else return dp [I] [j] = min (getdp (I, J-1), getdp (I + 1, j) + 1
}
Recursion (I refers to the start recursion with a small interval)
For (int I = 1; I <= n; I ++ ){
For (int j = 0; j <n-I; j ++ ){
If (a [j] = a [I + j]) dp [j] [I + j] = dp [j + 1] [I + J-1]
Else dp [j] [I + j] = min (dp [j + 1] [I + j], dp [j] [I + J-1]) + 1
}
}
Note the dp [I] [j] range I <= j
Thoughts:
1. if this question is another way of thinking, you can use
Assume that the maximum length of the string s and its inverse string s is L.
The number of characters to be added is the string length s-L.
2. In addition to using short to avoid MLE, you can also use the scrolling array or dynamic scrolling array that often appears in dp.
To save memory.
3. recursion is easy to crack the stack and can be used as an example.
4. I finally figured out why sometimes the program written uses c ++ to submit the AC, while g ++ to submit the AC.
Starting with computer principles:
Memory is actually a continuous piece. When applying for memory, some languages will forcibly check for out-of-bounds,
For example, java. C ++ is actually a pointer, for example, dp [0] is * dp,
Dp [1] is * (dp + 1 ). If the dp-1 memory is not used, then dp [-1] won't
An error is reported.
If the definition of a level-2 array dp is dp [2] [4], then
Dp [1] [-1] is actually dp [0] [3]. Some compilers will report errors and some will not.
In the memory, the second-level data is stored as follows:
Dp [0] [0], dp [0] [1],……, Dp [0] [M-1], dp [1] [0], dp [1] [1],...
In the compiler, array access is actually located in this way.
Dp [I] [j] = * (dp + I * M + j)
5. The most interesting thing is that I made a mistake in the dp initial conditions
Dp [I] [I + 1] = (a [I] = a [I + 1]? 0: 2). The result is written to the AC by recursion, And the AC by recursion.
It is wa. If it weren't for Recursive wa, I wouldn't find it wrong ..
Because the minimum number of characters to be added is
AB can be converted into abba, bab, and aba by adding at least one character.
Recursive AC code:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;short dp[5005][5005];char a[5010];int main(){ int n,i,j; while(scanf("%d",&n)!=EOF) { getchar(); gets(a); for(i=0;i<n;i++) { dp[i][i]=0; dp[i][i+1]=(a[i]==a[i+1]?0:1); } for(i=1;i<=n;i++) { for(j=0;j<n-i;j++) { if(a[j]==a[j+i]) dp[j][j+i]=dp[j+1][j+i-1]; else dp[j][j+i]=min(dp[j][j+i-1],dp[j+1][j+i])+1; } } printf("%d\n",dp[0][n-1]); } return 0;}//AC//1407MS
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;char a[5005];short dp[5005][5005];short getdp(int i,int j){ if(i==j) return 0; if(i+1==j) return a[i]==a[j]?0:1; if(dp[i][j]!=-1) return dp[i][j]; if(a[i]==a[j]) return dp[i][j]=getdp(i+1,j-1); else return dp[i][j]=min(getdp(i,j-1),getdp(i+1,j))+1;}int main(){ int n; while(scanf("%d",&n)!=EOF) { getchar(); gets(a); memset(dp,-1,sizeof(dp)); printf("%d\n",getdp(0,n-1)); } return 0;}//AC//1438MS