「暑期训练」「基础DP」 Common Subsequence (POJ-1458)

题意与分析

很简单:求最长公共子序列。
注意子序列与子串的差别:一个不连续一个连续。一份比较好的参考资料见:https://segmentfault.com/a/1190000002641054

状态转移方程是这样的:
d p [ i ] [ j ] 为a串1~i、b串1~j中的最长的公共子序列,则

d p [ i ] [ j ] = { d p [ i 1 ] [ j 1 ] + 1 ,     a [ i ] = b [ j ] , m a x ( d p [ i 1 ] [ j ] , d p [ i ] [ j 1 ] ) ,     a [ i ] b [ j ]

类似地,最长公共 子串是这样求的:
定义 d p [ i ] [ j ] 为以i、j为 末尾的最长子串,有
d p [ i ] [ j ] = { d p [ i 1 ] [ j 1 ] + 1 ,     a [ i ] = b [ j ] , 0 ,     a [ i ] b [ j ]

稍微不同地,多个字符串的公共子串/子序列求法如下:
https://blog.csdn.net/luxiaoxun/article/details/7915962
https://blog.csdn.net/liang5630/article/details/8095404
以后补题/训练的时候再仔细探讨。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define MP make_pair
#define PB push_back
#define fi first
#define se second
#define ZERO(x) memset((x), 0, sizeof(x))
#define ALL(x) (x).begin(),(x).end()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define QUICKIO                  \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
using namespace std;

template<typename T>
T read()
{
    T tmp; cin>>tmp;
    return tmp;
}

int dp[1005][1005];
string a,b;

int solve(int i,int j)
{
    if(i<0 || j<0) return 0;
    if(dp[i][j]!=-1)
        return dp[i][j];
    if(a[i]==b[j])
    {
        return dp[i][j]=solve(i-1,j-1)+1;
    }    
    else
    {
        return dp[i][j]=max(solve(i-1,j),solve(i,j-1));
    }
}

int main()
{
QUICKIO
    while(cin>>a>>b)
    {
        memset(dp,-1,sizeof(dp));
        cout<<solve(a.size()-1,b.size()-1)<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_17632793/article/details/81607910
今日推荐