粗体内容 说句实话我的能力还停留在那种二维线性/区间dp上...所以做这个题真的有点吃力,不过这个题的转态转移方程还是比较好推.我
推了方程到我看别人提交的代码,我浪费了6h...第一次推出方程写不出题,,,怎么说 尽量自己想...就是这个心态,我推出方程后不会处理...
一直输出别的数或者啥玩意的,最多输出的就是0...我给大家讲讲方程具体咋推的吧...然后再教大家咋写的(这个是看的最原始的那个大佬代码
以前还以为推出方程的dp就能写出来,果然还是我太年轻了hhh...
回归正题;不知道大家有没有做过牛客的那个括号匹配..和这个类似,就是个匹配问题..首先咋想到是用dp的呢?因为我太菜...学过的算法能用的
就贪心和dp可能还有二分.其实是直觉,因为dp就是减少暴力次数的一种算法..有点记忆化吧..50^50这个题最暴力的一个想法..然后讲讲为啥开
4维..因为数据50,遇到5000肯定二维,遇到1e5以上的要不就是一维要不就是一维带个状态..50要不3维要不4维嘛..然后根据题意4维最合适..
dp[i j][k l] i j为字符串a中i j的部分 k l为字符串b中k~l部分能否构成回文串
现在我要判断i j部分能否与k l部分构成回文串 dp无非就是转态转移因为是匹配嘛,所以很容易联想到dp[1][1][0][0]=1和dp[0][0][1][1]=1;
然后我们就会想怎么从上一个转态转移到->下一个转态;无非就两种情况现在的处境下来了一个a[j]或者b[l]都是从少的一步一步积累的嘛
先讲讲假如来a[j],因为位于a[]当前最后一个位子肯定是与最前面的a[i]和b[k]判断是否相等..假如a[j]==a[i]意味着我有可能组成回文串了
但是呢..我还要保证中间的也能组成回文串..假设我要转移的到的转态是dp[i][j][k][l]那我现在这个转态就是dp[i][j-1][k][l]..现在已经有了
a[j]==a[i]那我要满足就是dp[i+1][j-1][k][l]=1;->(这个就是保证中间的能否构成回文串)..其他三个方程和这个是一样的,我就不解释了...
下面讲讲我不会的4个for...4个for啊啊啊啊啊啊啊啊啊啊啊啊啊
我4个for写的i j k l这就是我写不出来的原因(因为平时就是这样写的嘛..)..第一个的for写的a数组中连续的个数 第二个for写的b数组中连续的个数 第三个for就是写的a数组的起点和终点 第四个for写的就是b数组的起点和终点..然后把他们进行一个一个的匹配...就没了
#include<bits/stdc++.h> #define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0) #define pb push_back #define inf 1329103910 typedef long long ll; const ll mod=1e9+7; const ll N=55; const double eps=1e-7; using namespace std; ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);} ll lcm(ll a,ll b) { return a*b/gcd(a,b); } ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;} ll Inv(ll x){ return qp(x,mod-2,mod);} ll C(ll n,ll m){if (m>n) return 0;ll ans = 1;for (int i = 1; i <= m; ++i) ans=ans*Inv(i)%mod*(n-i+1)%mod;return ans%mod;} int dp[N][N][N][N]; /* 四个维度分别用i j l k表示 分别表示 A中i~j 和 B中k~l */ char a[N]; char b[N]; int main() { int t,ans=0,n,m; cin>>t; while(t--) { ans=0; scanf("%s",a+1);n=strlen(a+1); scanf("%s",b+1);m=strlen(b+1); for(int d1=0;d1<=n;d1++) for(int d2=0;d2<=m;d2++) for(int i=1,j=d1;j<=n;i++,j++) for(int k=1,l=d2;l<=m;k++,l++) { if(d1+d2<=1) dp[i][j][k][l]=1; else { dp[i][j][k][l]=0; if(a[j]==a[i]&&d1>1) { if(dp[i+1][j-1][k][l]) dp[i][j][k][l]=1; } if(a[j]==b[k]&&d1&&d2) { if(dp[i][j-1][k+1][l]) dp[i][j][k][l]=1; } if(b[l]==a[i]&&d1&&d2) { if(dp[i+1][j][k][l-1]) dp[i][j][k][l]=1; } if(b[l]==b[k]&&d2>1) { if(dp[i][j][k+1][l-1]) dp[i][j][k][l]=1; } } if(dp[i][j][k][l])ans=max(ans,d1+d2); } cout<<ans<<endl; } return 0; }