经典模板
求两个字符串的最长公共子序列长度。
d
p
[
i
+
1
]
[
j
+
1
]
=
{
d
p
[
i
]
[
j
]
+
1
if
s
t
r
1
[
i
]
=
=
s
t
r
2
[
j
]
M
a
x
(
d
p
[
i
]
[
j
+
1
]
,
d
p
[
i
+
1
]
[
j
]
)
if
s
t
r
1
[
i
]
!
=
s
t
r
2
[
j
]
dp[i+1][j+1]=\begin{cases} dp[i][j] + 1 & \text{ if } str1[i] == str2[j]\\ Max(dp[i][j+1],dp[i+1][j]) & \text{ if } str1[i] != str2[j] \end{cases}
dp[i+1][j+1]={dp[i][j]+1Max(dp[i][j+1],dp[i+1][j]) if str1[i]==str2[j] if str1[i]!=str2[j]
dp[i+1][j+1]代表str1的0到i位置子串 和 str2的0到j位置的子串最长公共子序列
str1[i]和str2[j]如果相等,则其最长公共子序列长度为str[i-1]与str[j-1]最长公共子序列长度加一。否则为
str1[i]与str2[j-1] 或
str1[i-1]与str2[j]最长公共子序列最大值
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int[][] dp = new int[text1.length()+1][text2.length()+1];
for (int i = 0;i<text1.length();i++){
for(int j = 0; j < text2.length();j++){
if (text1.charAt(i) == text2.charAt(j)) {
dp[i+1][j+1] = dp[i][j] + 1;
} else {
dp[i+1][j+1] = Math.max(dp[i][j+1],dp[i+1][j]);
}
}
}
return dp[text1.length()][text2.length()];
}
}
变形例题
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
动态规划法
- 字符串反转,求两个字符串的最长公共子序列,总长度减去就行
#include<stdlib.h>
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
#define N 100
int dp[N][N];
string s1;
string s2;
int max(int a, int b){
return (a>b ? a : b);
}
int solve(){
int len = s1.size();
for (int i = 0; i<len; i++){
for (int j = 0; j<len; j++){
if (s1[i] == s2[j]){
dp[i + 1][j + 1] = dp[i][j] + 1;
}
else{
dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);
}
}
}
return len - dp[len][len];
}
int main(){
while (cin >> s1){
for (int i = 0; i<s1.size(); i++){
for (int j = 0; j<s1.size(); j++)dp[i][j] = 0;
}
s2 = "";
for (int i = 0; i<s1.size(); i++){
s2 = s2 + s1[s1.size() - 1 - i];
}
int res = solve();
cout << res << endl;
}
}
暴力法
假设初始字符串长度为0,逐渐往字符串后加字符。
arr[i]为从字符串str[i]开始到结束最长的回文串长度
#include<string>
#include<string.h>
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define MAX(a,b) (a>b?a:b)
#define N 1000+7
int main(){
string str;
while (cin >> str){
int arr[N];
memset(arr, 0, sizeof(arr));
int len = str.size();
for (int i = 1; i < len; i++){
//每添加一个字符,计算一次新字符串里最长的回文串的长度
for (int j = 0; j < i; j++){
if (str[i] == str[j]){
//更新数组
for (int k = 0; k <= j; k++){
if (arr[k] < arr[j + 1] + 2)
arr[k] = arr[j + 1] + 2;
}
}
}
//从str[i[到str[i]的字符串的最长回文串为自身,长度为1
arr[i] = 1;
}
cout << len - arr[0] << endl;
}
return 0;
}