LibreOJ 6163合并回文子串(二维区间dp)

合并回文子串

题意:

给你两个字符串a和b。
∣ c ∣ = ∣ a ∣ + ∣ b ∣ |c|=|a|+|b| c=a+b
之后再拼成字符串c。(a字符串内的相对顺序不变,b同样)

c最大的回文子串

思路:

传送门
这里做个dp时的补充。

  1. 当长度为0时,那么区间不存在,dp时把区间不存在的标记为1.(只有【a+1,a】时,才赋值1。其他都赋值0.)
  2. 利用好上面那个条件,可以少写好多状态。

AC

#include 
#include 
#include 
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn=55;
int dp[maxn][maxn][maxn][maxn];
char a[maxn],b[maxn];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--){
        mst(dp,0);
        cin>>(a+1)>>(b+1);
        int ans=0,len1=strlen(a+1),len2=strlen(b+1);
        for(int i=0; i<=len1; i++){
            for(int j=0; j<=len2; j++){
                for(int k=1; k+i-1<=len1; k++){
                    for(int p=1; p+j-1<=len2; p++){
                        int kk=k+i-1;
                        int pp=p+j-1;
                        if(i+j<=1)dp[k][kk][p][pp]=1;
                        else {
                            if(a[k]==a[kk])dp[k][kk][p][pp]|=dp[k+1][kk-1][p][pp];//假如区间长度为0.
                            if(b[p]==b[pp])dp[k][kk][p][pp]|=dp[k][kk][p+1][pp-1];
                            if(a[k]==b[pp])dp[k][kk][p][pp]|=dp[k+1][kk][p][pp-1];
                            if(b[p]==a[kk])dp[k][kk][p][pp]|=dp[k][kk-1][p+1][pp];
                        }
                        if(dp[k][kk][p][pp])ans=max(ans,i+j);
                    }
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(dp,#,区间dp)