Exemple de problème de programmation dynamique (3): la plus longue sous-séquence / chaîne commune; la sous-séquence / sous-chaîne de palindrome la plus longue

Remarque: Il n'est pas nécessaire que la sous-séquence soit continue, la sous-chaîne doit être continue.
1. La plus longue sous-séquence commune: étant
donné deux séquences, trouver la plus longue sous-séquence commune des deux séquences. Exemple:
Insérez la description de l'image ici
1.1. Sous-structure optimale:
Insérez la description de l'image ici
1.2. Pseudo-code:
Insérez la description de l'image ici
Insérez la description de l'image ici
Visualisation de la matrice c et b:
Insérez la description de l'image ici
1.3. Code 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();
   }	 
}

Référence: Solution de programmation dynamique à la plus longue sous-séquence commune (LCS)

2. La plus longue sous-chaîne commune:
remplace la plus longue else ifphrase de jugement de sous- séquence

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);
}

Référence: recherche la plus longue sous-chaîne commune de deux chaînes

3. La sous-séquence palindrome la plus longue: les
caractères de la chaîne sont symétriques et sont appelés palindrome. Par exemple, wbcdcbw dans la chaîne wabcdcbwq est la sous-séquence palindrome, bcdcb est la sous-séquence palindrome.
Solution:
retournez la chaîne s et changez-la en s ', puis utilisez la méthode de sous-séquence commune pour résoudre.

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 plus longue sous-chaîne de palindrome:
4.1 Version de programmation dynamique:
S signifie chaîne, i et j représentent les positions de début et de fin.
Condition initiale (condition aux limites): Lorsque la longueur est inférieure à 2, la plage de dp (i + 1, j -1) est fausse, donc la longueur est 1, 2 est la condition aux limites
a) dp [i] [i] = vrai (utilisé dans le code 1 signifie)
b) Si S [i] = S [i + 1], alors dp [i] [i + 1] = true L'
équation de transition d'état:
a) If (dp (i + 1, j -1) == vrai && S [i] == S [j]) alors dp (i, j) = vrai
b) if (dp (i + 1, j -1) == faux || S [i]! = S [j ]) alors dp (i, j) = faux

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);//获取最长回文子串
    }
};

Matériel de référence: solution C ++ de la plus longue sous-chaîne palindrome 3: programmation dynamique

4.2 La méthode d'expansion centrale:
comment récupérer la chaîne de texte dans la méthode de diffusion centrale?
À partir de chaque position, étalez-vous des deux côtés. Terminez quand ce n'est pas un palindrome. Par exemple, str=acdbbdaanous devons trouver le palindrome le plus long à partir du premier b (position 3). Comment trouver?
Tout d'abord, recherchez le même caractère que la position actuelle sur la gauche jusqu'à ce qu'il rencontre une inégalité.
Ensuite, allez à droite pour trouver le même caractère que la position actuelle jusqu'à ce qu'il rencontre une inégalité.
Enfin, il se propage dans les deux sens jusqu'à ce que la gauche et la droite ne soient pas égales. Comme le montre la figure ci-dessous:
Insérez la description de l'image ici
une taille de fenêtre (len) apparaîtra à chaque position s'étendant des deux côtés. Si len>maxLen(utilisé pour indiquer la longueur du palindrome le plus long). La maxLenvaleur mise à jour .
Parce que la dernière chose que nous voulons retourner est la sous-chaîne spécifique, pas la longueur, nous devons donc également enregistrer la position de départ (maxStart) à maxLen, c'est-à-dire maxStart = len à ce moment.

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);
}

Matériel de référence: méthode de diffusion centrale

Pour résumer:

1. La clé de la programmation dynamique: trouver la sous-structure optimale, c'est-à-dire trouver l'état initial et l'équation de transition d'état.

Je suppose que tu aimes

Origine blog.csdn.net/qq_33726635/article/details/105933862
conseillé
Classement