NYOJ-37 回文字符串 —— LCS变形
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=37
题解:
一开始想从两边向中间添加字符,发现这样不是最优的。因为加入字符之后,这些原本存在的字符是离散的,所以就不能用顺序的方法去添加。
正确做法是将字符串逆过来,与原字符串求最大公共子序列。最大公共子序列即是不需要添加的字符序列,那么剩下的len-dp[len][len]就是需要添加进去的最少字符个数,使得原来的字符串刚好构成回文串。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 #define eps 0.0000001 17 typedef long long LL; 18 const int INF = 2e9; 19 const LL LNF = 9e18; 20 const int mod = 1e9+7; 21 const int maxn = 1000+10; 22 23 char s[maxn]; 24 int dp[maxn][maxn]; 25 26 void solve() 27 { 28 scanf("%s",s); 29 int len = strlen(s); 30 for(int i = 0; i<len; i++) 31 { 32 for(int j = 0; j<len; j++) 33 { 34 if(s[i]==s[len-1-j]) 35 dp[i+1][j+1] = dp[i][j] + 1; 36 else 37 dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]); 38 } 39 } 40 printf("%d\n", len-dp[len][len]); 41 } 42 43 int main() 44 { 45 int T; 46 scanf("%d",&T); 47 while(T--){ 48 ms(dp,0); 49 solve(); 50 } 51 }