合并回文子串------------------------------------思维(区间dp求最长回文字符串)

在这里插入图片描述
在这里插入图片描述

本篇先讲述:动态规划求解最长回文字符串长度

令f[i][j]:表示s[i]至s[j]所表示的子串是否为回文串,是为1,否为0.
根据s[i]和s[j]是否相等划分子集

1.s[i]==s[j],那么只要s[i+1]至s[j-1]是回文子串,那么s[i]至s[j]一定是回文子串。如果s[i+1]至s[j-1]不是回文子串,那么s[i]至s[j]也一定不是回文子串

2.s[i]!=s[j] 那么s[i]至s[j]一定不是回文子串

状态方程:

在这里插入图片描述

再回到本题,因为本题是2个字符串。所以我们把二维扩展到四维

f[sa][ea][sb][eb]:表示a的sa ~ ea 和 b的sb ~ eb可以构成回文子串的最大长度

转移方程:

	if(a[sa]==a[ea])  f[sa][ea][sb][eb]|=f[sa+1][ea-1][sb][eb];
	if(b[sb]==b[eb])  f[sa][ea][sb][eb]|=f[sa][ea][sb+1][eb-1];
	if(a[sa]==b[eb])  f[sa][ea][sb][eb]|=f[sa+1][ea][sb][eb-1];
	if(a[ea]==b[sb])  f[sa][ea][sb][eb]|=f[sa][ea-1][sb+1][eb];

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int f[N][N][N][N];
int t;
char a[N],b[N];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s %s",(a+1),(b+1));
		int ans=-1;
		int lena=strlen(a+1);
		int lenb=strlen(b+1);
		for(int la=0;la<=lena;la++) //枚举a串的长度
			for(int lb=0;lb<=lenb;lb++)//枚举b串的长度
			{
				for(int sa=1;sa+la-1<=lena;sa++) //枚举a串起点
				{
					for(int sb=1;sb+lb-1<=lenb;sb++)//枚举b串起点
					{
						int ea=sa+la-1;int eb=sb+lb-1;//a,b串终点
						if(la+lb<=1) f[sa][ea][sb][eb]=1;//长度为1的串,初始化为1
						else
						{
							f[sa][ea][sb][eb]=0;
							if(a[sa]==a[ea]) f[sa][ea][sb][eb]|=f[sa+1][ea-1][sb][eb];
							if(b[sb]==b[eb]) f[sa][ea][sb][eb]|=f[sa][ea][sb+1][eb-1];
							if(a[sa]==b[eb])  f[sa][ea][sb][eb]|=f[sa+1][ea][sb][eb-1];
							if(a[ea]==b[sb]) f[sa][ea][sb][eb]|=f[sa][ea-1][sb+1][eb];
							
						}
						//1表示是回文串,所以取长度la+lb
						if(f[sa][ea][sb][eb])  ans=max(ans,la+lb);
					}
				}
			}
		cout<<ans<<endl;
	 } 
}
发布了572 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/105282586