51Nod 1092 回文字符串(LCS + dp)

51Nod 1092

数据结构暑假作业上出现的一题,学习了一下相关算法之后,找到了oj测试能AC。

1.回文串是一种中心对称的结构,这道题可以转变为求最长回文子序列长度的题目。(子序列:可以不连续)

 

2.可以得到公式: ans(最少插入字符)= 字符串总长度 - 最长回文子序列长度

 

3.如何求最长回文子序列的长度呢? wsx dalao的思路是对区间进行维护(我暂时还写不出来),更一般的做法是动态规划(Dynamic Programming)。

dp 粗略的可以理解为一个状态向另一个状态的转移。一个维度表示一个变量。

仔细想一下的话,很难发现最长回文子序列的长度可以变为求原字符串与其反转字符串最长公共子序列长度(LCS)的题目。

求 LCS 就可以与 dp 联系起来了。

下面列一下状态转移方程:

 1 /**
 2  *  Night gathers, and now my watch begins.
 3  *  It shall not end until my death.
 4  *  I shall take no wife, hold no lands, father no children.
 5  *  I shall wear no crowns and win no glory.
 6  *  I shall live and die at my post.
 7  *  I am the sword in the darkness.
 8  *  I am the watcher on the walls.
 9  *  I am the fire that burns against the cold,
10  *  the light that wakes the sleepers,
11  *  the shield that guards the realms of men.
12  *  I pledge my life and honor to the Night's Watch,
13  *  for this night,
14  *  and all the nights to come.
15  */
16 
17 #include<bits/stdc++.h>
18 #define lson i<<2
19 #define rson i<<2|1
20 #define LS l,mid,lson
21 #define RS mid+1,r,rson
22 #define mem(a,x) memset(a,x,sizeof(a))
23 #define gcd(a,b) __gcd(a,b)
24 #define ll long long
25 #define ull unsigned long long
26 #define lowbit(x) (x&-x)
27 #define pb(x) push_back(x)
28 #define enld endl
29 #define mian main
30 #define itn int
31 #define prinft printf
32 #pragma GCC optimize(2)
33 #pragma comment(linker, "/STACK:102400000,102400000")
34 
35 const double PI = acos (-1.0);
36 const int INF = 0x3f3f3f3f;
37 const int EXP = 1e-8;
38 const int N = 1e5 + 5;
39 const int MOD = 1e9 + 7;
40 const int MAXN = 1e3 + 20;
41 
42 using namespace std;
43 
44 string s;   //题目给的原字符串
45 string sr;  //原字符串的翻转字符串
46 int dp[MAXN][MAXN]; //dp[i+1][j+1]状态表示为 (s0 ~ si) 和 (s0 ~ sj) 的LCS
47 
48 int main() {
49     cin >> s;
50     mem (dp, 0);    //dp数组初始化
51     sr = s;
52     reverse (sr.begin(), sr.end()); //构造翻转串
53     for (itn i = 1; i <= s.size(); ++i)
54         for (int j = 1; j <= sr.size(); ++j)
55             if (s[i - 1] == sr[j - 1])
56                 dp[i][j] = dp[i - 1][j - 1] + 1;
57             else
58                 dp[i][j] = max (dp[i - 1][j], dp[i][j - 1]);
59     cout << s.size() - dp[s.size()][sr.size()] << endl; //ans = s的长度 - LCS(s, sr)
60     return 0;
61 }

 

转载于:https://www.cnblogs.com/chunibyo/p/9479545.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值