题目复述:
# [蓝桥杯 2016 省 A] 密码脱落
## 题目描述
X 星球的考古学家发现了一批古代留下来的密码。
这些密码是由 A、B、C、D 四种植物的种子串成的序列。
仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的回文串)。
由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。
你的任务是:
给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。
## 输入格式
输入一行,表示现在看到的密码串。(长度不大于 $1000$)
## 输出格式
要求输出一个正整数,表示至少脱落了多少个种子。
## 样例 #1
### 样例输入 #1
```
ABCBA
```
### 样例输出 #1
```
0
```
## 样例 #2
### 样例输入 #2
```
ABDCDCBABC
```
### 样例输出 #2
```
3
```
## 提示
蓝桥杯 2016 年省赛 A 组 I 题。
最长公共子序列-代码:
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
int main()
{
string s;
cin >> s;
int n = s.size();
string s1 = s;
reverse(s1.begin(), s1.end());
int dp[1005][1005];
memset(dp,0,sizeof(dp));
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
if (s[i-1] == s1[j-1])
{
dp[i][j] = dp[i-1][j-1]+1;
}
else
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout << n - dp[n][n];
return 0;
}
最长公共子序列--思路介绍:
这题看上去很简单,但其实要搞懂还是需要一定的做题积累的,不然很难看出来这道题到底想考什么,提到回文串,大家都知道是从左往右和从右往左一样,所以可以换句话说,如果原串是S,那么将S进行首尾颠倒后得到S1,那么S应该等于S1,这样就可以证明这是回文串。
这道题需要大家知道一个概念--“最长公共子序列”,【模板】最长公共子序列 - 洛谷,不然的话可能很难做出这道题来。为什么要用到这个概念,就是我上面提到的,颠倒后的S1等于S则证明是回文串,那么由于这道题是将回文串进行涂抹,不妨举个例子,假设原来的回文串是ABCDCBA,我们抹去第一个B,原串变成A_CDCBA,颠倒后变成ABCDC_A,我们再来找一下两个的最长公共子序列,发现是ACDCA,正好把删去的一个B给省略了,也就是说找到最长公共子序列可以完美避开这种被抹去一个数的情况,如果两个数都被抹去了,那干脆不用找它了,如果都没被抹去,正好会被计算进最长公共子序列中;
所以最后的答案便是原串的长度n减去最长公共子序列的长度,上面的例子中n=6,最长公共子序列=5,所以答案为1正好是缺的那个B!
所以本题的告诉大家,提到回文的时候可以想想最长公共子序列是否可以解决,吃一堑长一智~