转化为取两次相同的方案数
f[i][j][k][p]
p=i+j-k去掉一维
滚动数组去掉一维
可能的有值的f[2][j][k]不多,转移的时候if(!f[tmp][j][k]) continue 会快7倍
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define reg register int #define il inline #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=505; const int mod=1024523; int f[2][N][N]; char s1[N],s2[N]; int n,m; int main(){ rd(n);rd(m); scanf("%s",s1+1);scanf("%s",s2+1); f[0][0][0]=1; int tmp=0; for(reg i=0;i<=n;++i){ tmp^=1; for(reg j=0;j<=m;++j){ for(reg k=0;k<=n;++k){ f[tmp][j][k]=0; } } for(reg j=0;j<=m;++j){ for(reg k=0;k<=n;++k){ int p=i+j-k; if(p<0) break; int lp=f[tmp^1][j][k]; if(!lp) continue; //cout<<" i "<<i<<" j "<<j<<" k "<<k<<" p "<<p<<":: "<<f[tmp^1][j][k]<<endl; if(i<n&&k<n&&s1[n-i]==s1[n-k]){ f[tmp][j][k+1]=(f[tmp][j][k+1]+lp)%mod; } if(i<n&&p<m&&s1[n-i]==s2[m-p]){ f[tmp][j][k]=(f[tmp][j][k]+lp)%mod; } if(j<m&&k<n&&s2[m-j]==s1[n-k]){ f[tmp^1][j+1][k+1]=(f[tmp^1][j+1][k+1]+lp)%mod; } if(j<m&&p<m&&s2[m-j]==s2[m-p]){ f[tmp^1][j+1][k]=(f[tmp^1][j+1][k]+lp)%mod; } } } } tmp^=1; printf("%d",f[tmp][m][n]); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2018/12/31 17:47:39 */