合并回文子串 区间dp

链接:https://ac.nowcoder.com/acm/problem/13230
来源:牛客网

题目描述
输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变。如"abc"和"xyz"可以被组合成"axbycz"或"abxcyz"等。
我们定义字符串的价值为其最长回文子串的长度(回文串表示从正反两边看完全一致的字符串,如"aba"和"xyyx")。
需要求出所有可能的C中价值最大的字符串,输出这个最大价值即可
输入描述:
第一行一个整数T(T ≤ 50)。
接下来2T行,每两行两个字符串分别代表A,B(|A|,|B| ≤ 50),A,B的字符集为全体小写字母。
输出描述:
对于每组数据输出一行一个整数表示价值最大的C的价值。
示例1
输入
2
aa
bb
a
aaaabcaa
输出
4
5
很明显这道题是dp题,因为我们假设dp[i][j][k][p]表示的是选择字符串a第i到j,字符串b第k到p的串。我们来思考下状态转移方程!
当a[i]==a[j]的时候,这个时候,最长的回文串是什么?毫无疑问,将a[i]与a[j]拼接到串a[i+1][j-1][k][p]当中即可。
当a[i]==b[p],b[k]==a[j],b[k]==b[p]都是如此。

注意写区间dp要从小区间更新大区间,那怎么做呢?枚举区间长度即可!(边界处理有点难)

#include<iostream>
#include<cstdio>
#define mmax 55
using namespace std;
int dp[55][55][55][55];
int main (){
    int T;
    cin>>T;
    while(T--){
    string a,b;
    cin>>a>>b;
    int len1=a.size();
    int len2=b.size();
    int inf=0;
    for(int i=0;i<=len1;i++){//第一段区间的长度
        for(int j=0;j<=len2;j++){//第二段区间的长度
            for(int k=0;k<=len1;k++){//第一段区间的起点,这里要多出来一个空间
                int xend=k+i;//第一段区间终点+1
                if(xend>len1){//终点超出数组长度
                    break;
                }
                for(int p=0;p<=len2;p++){//第二段区间的起点
                    int yend=p+j;
                    if(yend>len2){
                        break;
                    }
                    int x=k,y=p;
                    if(i+j<=1){//不管选不选,小于等于一个字母一定是回文串
                        dp[x][xend][y][yend]=1;
                    }
                    else{
                        dp[x][xend][y][yend]=0;
                        if(x<=xend-2&&a[x]==a[xend-1]){
                        dp[x][xend][y][yend]|=dp[x+1][xend-1][y][yend];
                    }
                        if(x+1<=xend&&y<=yend-1&&a[x]==b[yend-1]){
                        dp[x][xend][y][yend]|=dp[x+1][xend][y][yend-1];
                    }
                        if(x<=xend-1&&y+1<=yend&&b[y]==a[xend-1]){
                        dp[x][xend][y][yend]|=dp[x][xend-1][y+1][yend];
                    }
                        if(y<=yend-2&&b[y]==b[yend-1]){
                        dp[x][xend][y][yend]|=dp[x][xend][y+1][yend-1];
                    }
                    }
                    if(dp[x][xend][y][yend])
                    inf=max(inf,i+j);
                   // printf("%d %d %d %d %d\n",x,xend,y,yend,dp[x][xend][y][yend]);
                }
            }
        }
    }
        cout<<inf<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章