转化

容易发现题目中所求的其实可以看成取2次,而且2次取出的序列相同的方案数。

DP

考虑动态规划,设为第一次第1行取到第个,第2行取到第个,第二次第1行取到第个,第2行取到第个,其中且两次取到序列相同的方案数。答案即为。由于空间不够根据可以压掉一维,由于只与有关所以可以滚动一维。最后时间复杂度空间复杂度

CODE

#include<bits/stdc++.h>
using namespace std;
#define I inline 
#define ri register int
#define ll long long
#define For(i , x , y) for(ri i = x ; i <= y ; ++ i)
#define Next(i , u) for(ri i = head[u] ; i ; i = e[i].nxt)

I int read() {
    int s = 0 ,w = 1; char ch = getchar();
    while(ch < 48 || ch > 57) {if(ch == '-') w = -1; ch = getchar();}
    while(ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48) , ch = getchar();
    return s * w;
}

const int P = 1024523 , N = 505;

int n , m , f[10][N][N];
char s[N] , t[N];

signed main() {
    n = read() , m = read();
    scanf("%s%s" , s + 1 , t + 1);
    reverse(s + 1 , s + n + 1);
    reverse(t + 1 , t + m + 1);

    f[0][0][0] = 1;
    int u = 0 ;
    for(ri i = 0; i <= n ; ++ i , u ^= 1)
        For(j , 0 , m)
            For(k , 0 , n) {
                int l = i + j - k, tmp = f[u][j][k]; 
                if(l < 0 || l > m) continue;
                if(s[i + 1] == s[k + 1]) (f[u ^ 1][j][k + 1] += tmp) %= P;
                if(t[j + 1] == t[l + 1]) (f[u][j + 1][k] += tmp) %= P;
                if(s[i + 1] == t[l + 1]) (f[u ^ 1][j][k] += tmp ) %= P;
                if(t[j + 1] == s[k + 1]) (f[u][j + 1][k + 1] += tmp) %= P;
                f[u][j][k] = 0;
            }
    cout << f[u][m][n] << endl;
    return 0;
}