牛客每日一題3.26 合併迴文子串 動態規劃

首先這種題肯定是動態規劃!!!!!不要往其他地方想。要怎麼做呢先從單個串要怎麼判斷區間最長迴文來說。單個串如果要判斷任意一個區間[L,R]是不是迴文可以去寫區間dp,對於一個串長度大於2的迴文串,如果要在此基礎上在延長串的長度必然是在頭尾加兩個,所以對於一個串的就可以寫出方程 f[L][R] |= F[L+1][R-1],(當a[L]==a[R]時);
現在到了兩個串,其實思路差不多,兩個串要拼出一個迴文串也必然要在原先滿足的基礎上在加兩個字母。那麼我們這麼設計狀態
f[i][[j][x][y],代表A串使用了[i,j], B串使用了[x,y]能不能構成迴文。
如果是在原先的迴文串基礎上增加兩個字母,則哪個字母當頭,哪個字母當尾,必然只有四種情況.
在這裏插入圖片描述
解釋一下第一個其他都是同理可得,當A串的i位置的字母等於B串j位置的字符,則我們可以看A的[i + 1, j -1]和B串的[x, y ]能不能構成迴文,如果可以,則[i,j] [x,y]必然也是一個迴文串。

這樣子去枚舉就可以啦,真的十分的暴力。複雜度是O(Tn*4)
其他注意的要點就是i和x要倒序枚舉,因爲你前面的狀態需要後面的狀態。還有就是當區間+1,-1後變成非法區間,就僅僅判斷剩下那個合法區間是不是迴文串就可以了!最後代碼跑579ms還行。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<time.h>
#include<string>
#include<cmath>
#include<stack>
#include<map>
#include<set>
#define int long long
#define double long double
using namespace std;
#define PI  3.1415926535898
#define eqs 1e-17
const long long max_ = 50 + 2;
const int mod = 1e9 + 7;
const int inf = 1e9 + 7;
const long long INF = 1e18;
int read() {
	int s = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch>'9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0'&&ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * f;
}
inline void write(int x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}
inline int min(int a, int b) {
	return a < b ? a : b;
}
inline int max(int a, int b) {
	return a > b ? a : b;
}
bool f[max_][max_][max_][max_];
int ans;
char a[max_], b[max_];
//00 01 10 11
// 0  1  2 3
int pana[max_][max_], panb[max_][max_],lena,lenb;
void solve() {
	for (int len = 1; len <= min(lena,2); len++) {
		for (int L = 1, R = len; R <= lena; L++, R++) {
			//[L,R]
			if (a[L] == a[R]) {
				pana[L][R] = 1;
			}
		}
	}
	for (int len = 3; len <= lena; len++) {
		for (int L = 1, R = len;  R <= lena; L++, R++) {
			//[L,R]
			if (a[L] == a[R]) {
				pana[L][R] |= pana[L + 1][R - 1];
			}
		}
	}

	for (int len = 1; len <= min(lenb, 2); len++) {
		for (int L = 1, R = len; R <= lenb; L++, R++) {
			//[L,R]
			if (b[L] == b[R]) {
				panb[L][R] = 1;
			}
		}
	}
	for (int len = 3; len <= lenb; len++) {
		for (int L = 1, R = len; R <= lenb; L++, R++) {
			//[L,R]
			if (b[L] == b[R]) {
				panb[L][R] |= panb[L + 1][R - 1];
			}
		}
	}
}
signed main() {
	int T;
	cin >> T;
	while (T--){
		cin >> a + 1 >> b + 1;
		 lena = strlen(a + 1), lenb = strlen(b + 1);
		ans = 1; 
		solve();
		for (int i = lena; i >= 1; i--) {
			for (int j = i; j <= lena; j++) {
				for (int x = lenb; x >= 1; x--) {
					for (int y = x; y <= lenb; y++) {
						if (a[i] == a[j] && i < j) {
							if (i + 1 <= j - 1) {//合法狀態
								f[i][j][x][y] |= f[i + 1][j - 1][x][y];
							}
							else f[i][j][x][y] |= panb[x][y];
						}
						if (a[i] == b[y]) {
							if (i == j && x == y)f[i][j][x][y] = 1;//同時不合法
							if (i == j) {
								f[i][j][x][y] |= panb[x][y - 1];
							}
							if (x == y) {
								f[i][j][x][y] |= pana[i + 1][j];
							}
							f[i][j][x][y] |= f[i + 1][j][x][y - 1];
						}
						if (b[x] == a[j] ) {
							if (i == j && x == y)f[i][j][x][y] = 1;//同時不合法
							if (i == j) {
								f[i][j][x][y] |= panb[x + 1][y];
							}
							if (x == y) {
								f[i][j][x][y] |= pana[i][j - 1];
							}
							f[i][j][x][y] |= f[i][j - 1][x + 1][y];
						}
						if (b[x] == b[y] && x < y) {
							if (x + 1 <= y - 1) {
									f[i][j][x][y] |= f[i][j][x + 1][y - 1];
							}else 	f[i][j][x][y] |= pana[i][j];
						}
						if(f[i][j][x][y])
							ans = max(ans, (j - i + 1) + (y - x + 1));
					}
				}
			}
		}
		cout << ans << endl;
		memset(pana, 0, sizeof(pana));
		memset(panb, 0, sizeof(panb));
		memset(f, 0, sizeof(f));
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章