Nota: No se requiere que la subsecuencia sea continua, se requiere que la subcadena sea continua.
1. La subsecuencia común más larga:
Dadas dos secuencias, encuentre la subsecuencia común más larga de las dos secuencias. Ejemplo:
1.1. Subestructura óptima:
1.2. Pseudocódigo:
Visualización de la matriz cyb:
1.3. Código C ++ :
#include <iostream>
#include <vector>
#include <string>
#include <stack>
using namespace std;
string getLCS(string s1, string s2)
{
//此部分获得最长值
int m=s1.length()+1;
int n = s2.length()+1;
vector< vector<int> > c(m, vector<int>(n)); //计算长度
vector< vector<int> > b(m, vector<int>(n)); // 字串遍历
for(int i = 0;i<m;i++) {
c[i][0] = 0; } // 初始条件(边界条件)
for(int i = 0;i<n;i++) {
c[0][i] = 0; } // 同上
for(int i = 0;i<m-1;i++){
for(int j = 0;j<n-1;j++){
if(s1[i] == s2[j]) {
c[i+1][j+1] = c[i][j] + 1;
b[i+1][j+1] = 1; // 1 表示相同
}
else if(c[i][j+1]>c[i+1][j]){
c[i+1][j+1] = c[i][j+1];
b[i+1][j+1] = 2; // 2 表示不同
}
else{
c[i+1][j+1] = c[i+1][j];
b[i+1][j+1] = 3; // 3表示不同
}
}
}
//此部分获得公共子序列
stack<char> LCSans;
for(i = m-1,j = n-1; i>=0 && j>=0; ;){
if(b[i][j] == 1){
LCSans.push_back(s1[i]);
i--;
j--;
}
else if(b[i][j] == 2)
i--;
else
j--;
}
// 此部分输出子序列
while(!LCSans.empty()) {
cout<<LCSans.top();
LCSans.pop();
}
}
Referencia: solución de programación dinámica para la subsecuencia común más larga (LCS)
2. La subcadena común más larga:
reemplaza la else if
sentencia de juicio posterior más larga
string getLCS(string str1, string str2) {
int m=s1.length()+1;
int n = s2.length()+1;
int maxlen = 0;
int end;
vector< vector<int> > c(m, vector<int>(n)); //计算长度
for(int i = 0;i<m;i++) {
c[i][0] = 0; } // 初始条件(边界条件)
for(int i = 0;i<n;i++) {
c[0][i] = 0; } // 同上
for(int i = 0;i<m-1;i++){
for(int j = 0;j<n-1;j++){
if(s1[i] == s2[j]) {
c[i+1][j+1] = c[i][j] + 1;
}
else {
c[i+1][j+1] = 0;
}
if(c[i+1][j+1]>maxlen){
maxlen = c[i+1][j+1];
end = i;
}
}
}
return str1.substr(end - maxlen + 1, maxlen);
}
Referencia: Encuentre la subcadena común más larga de dos cadenas
3. La subsecuencia palíndromo más larga: los
caracteres de la cadena son simétricos y se denominan palíndromo. Por ejemplo, wbcdcbw en la cadena wabcdcbwq es la subsecuencia palíndromo; bcdcb es la subsecuencia palíndromo.
Solución:
voltee la cadena sy cámbiela por s ', y use el método de subsecuencia común para resolver.
string longestPalindrome(string s) {
if(s.length()==1) return s;//大小为1的字符串必为回文串
string rev=s;//rev存放s反转结果
string res;//存放结果
std::reverse(rev.begin(),rev.end());
if(rev==s) return s;
//从此开始调用最长公共子序列算法。
4. La subcadena palíndromo más larga:
4.1 Versión de programación dinámica:
S significa cuerda, iyj significan posiciones inicial y final.
Condición inicial (condición de límite): cuando la longitud es menor que 2, el rango de dp (i + 1, j -1) es incorrecto, por lo que la longitud es 1, 2 es la condición de límite
a) dp [i] [i] = verdadero (usado en el código 1 significa)
b) Si S [i] = S [i + 1], entonces dp [i] [i + 1] = verdadero La
ecuación de transición de estado:
a) Si (dp (i + 1, j -1) == verdadero && S [i] == S [j]) entonces dp (i, j) = verdadero
b) si (dp (i + 1, j -1) == falso || S [i]! = S [j ]) entonces dp (i, j) = falso
class Solution {
public:
string longestPalindrome(string s) {
int len=s.size();
if(len==0||len==1)
return s;
int start=0;//回文串起始位置
int max=1;//回文串最大长度
vector<vector<int>> dp(len,vector<int>(len));//定义二维动态数组
for(int i=0;i<len;i++)//初始化状态
{
dp[i][i]=1; //单个元素是回文串
if(i<len-1&&s[i]==s[i+1]) //两个元素相同也是回文串
{
dp[i][i+1]=1;
max=2;
start=i;
}
}
for(int l=3;l<=len;l++)//l表示检索的子串长度,等于3表示先检索长度为3的子串
{
for(int i=0;i+l-1<len;i++)
{
int j=l+i-1;//终止字符位置
if(s[i]==s[j]&&dp[i+1][j-1]==1)//状态转移
{
dp[i][j]=1;
start=i;
max=l;
}
}
}
return s.substr(start,max);//获取最长回文子串
}
};
Material de referencia: solución C ++ de la subcadena 3 del palíndromo más larga: programación dinámica
4.2 El método de expansión central:
¿cómo recuperar la cadena de texto en el método de difusión central?
Comenzando desde cada posición, extiéndase a ambos lados. Termina cuando no es un palíndromo. Por ejemplo, str=acdbbdaa
necesitamos encontrar el palíndromo más largo a partir de la primera b (posición 3). ¿Como encontrar?
Primero, busque el mismo carácter que la posición actual a la izquierda hasta que encuentre desigualdad.
Luego vaya a la derecha para encontrar el mismo carácter que la posición actual hasta que encuentre desigualdad.
Finalmente, se propaga en ambas direcciones hasta que la izquierda y la derecha no son iguales. Como se muestra en la figura siguiente:
aparecerá un tamaño de ventana (largo) en cada posición que se extenderá a ambos lados. Si len>maxLen
(usado para indicar la longitud del palíndromo más largo). El maxLen
valor actualizado .
Debido a que lo último que queremos devolver es la subcadena específica, no la longitud, también necesitamos registrar la posición inicial (maxStart) en maxLen, es decir, maxStart = len en este momento.
string LPS(string s)
{
int maxstart = 0;
int maxlen = 1;
int start = 0;
int len = 1;
if(s.size()<=1) return s;
for(int i = 0;i<s.size();i++){
int l = i--;
int r = i++;
while(l>=0 && s[l] == s[i]) {
start = l; len++; l--}
while(r<s.size() && s[r] == s[i]) {
len++; r++}
while(l>=0 && r<s.size() && s[l] == s[r]) {
start= l;
l--;
r++;
len = len+2;
}
if(len > maxlen) {
maxstart = start; maxstart = start;}
len = 1;
}
return s.substring(maxstart,maxlen);
}
Material de referencia: método de difusión central
para resumir:
1. La clave de la programación dinámica: encontrar la subestructura óptima, es decir, encontrar el estado inicial y la ecuación de transición de estado.