传送门
思路:
设 f [ i ][ j ][ k ][ 0/1 ] 表示 A 串匹配到第 i 个,B 串匹配到第 j 个,已经匹配到第 k 段,0: A[ i ] 与 B[ j ] 不匹配, 1: A[ i ] 与 B[ j ] 匹配。
状态转移可分为 A[ i ] 与 B[ j ] 匹配和不匹配两种状态:
① 若不匹配, f [ i ][ j ][ k ][ 0 ] = f [ i-1 ][ j ][ k ][ 0 ] + f [ i-1 ][ j ][ k ][ 1 ] 。
② 匹配,f [ i ][ j ][ k ][ 1 ] = f [ i-1 ][ j-1 ][ k-1 ][ 1 ] + f [ i-1 ][ j-1 ][ k-1 ][ 0 ] + f [ i-1 ][ j-1 ][ k ][ 1 ] 。
如果直接将 f 数组开到 4 维,128M 的空间明显不够。
考虑到每次的状态转移只和前一次的状态有关,所以可以将 f 的第一维用二进制滚动 。
Code:
70 Points:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<cstdlib> #include<stack> #include<vector> #include<queue> #include<deque> #include<map> #include<set> using namespace std; #define lck_max(a,b) ((a)>(b)?(a):(b)) #define lck_min(a,b) ((a)<(b)?(a):(b)) typedef long long LL; const int maxn=101; const int mod=1e9+7; LL n,m,K,ans,f[(maxn<<1)+(maxn<<3)][maxn<<1][maxn<<1][2]; char s1[(maxn<<1)+(maxn<<3)],s2[maxn<<1]; inline LL read() { LL kr=1,xs=0; char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline void out(LL xs) { if(!xs) {putchar(48); return;} if(xs<0) putchar('-'),xs=-xs; int kr[57],ls=0; while(xs) kr[++ls]=xs%10,xs/=10; while(ls) putchar(kr[ls]+48),ls--; } int main() { n=read();m=read();K=read(); scanf("%s",s1+1);scanf("%s",s2+1); f[0][0][0][0]=1; for(LL i=1;i<=n;i++) { f[i][0][0][0]=1; for(LL j=1;j<=m;j++) { for(LL k=1;k<=K;k++) { f[i][j][k][0]=(f[i-1][j][k][0]+f[i-1][j][k][1])%mod; if(s1[i]==s2[j]) f[i][j][k][1]=(f[i-1][j-1][k][1]+f[i-1][j-1][k-1][0]+f[i-1][j-1][k-1][1])%mod; } } } out((f[n][m][K][0]+f[n][m][K][1])%mod); return 0; }
100 Points:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<cstdlib> #include<stack> #include<vector> #include<queue> #include<deque> #include<map> #include<set> using namespace std; #define lck_max(a,b) ((a)>(b)?(a):(b)) #define lck_min(a,b) ((a)<(b)?(a):(b)) typedef long long LL; const int maxn=101; const int mod=1e9+7; bool pos=true; LL n,m,K,ans,f[2][maxn<<1][maxn<<1][2]; char s1[(maxn<<1)+(maxn<<3)],s2[maxn<<1]; inline LL read() { LL kr=1,xs=0; char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline void out(LL xs) { if(!xs) {putchar(48); return;} if(xs<0) putchar('-'),xs=-xs; int kr[57],ls=0; while(xs) kr[++ls]=xs%10,xs/=10; while(ls) putchar(kr[ls]+48),ls--; } int main() { n=read();m=read();K=read(); scanf("%s",s1+1);scanf("%s",s2+1); f[0][0][0][0]=1;f[1][0][0][0]=1; for(LL i=1;i<=n;i++,pos^=1) { for(LL j=1;j<=m;j++) { for(LL k=1;k<=K;k++) { f[pos][j][k][0]=(f[pos^1][j][k][0]+f[pos^1][j][k][1])%mod; if(s1[i]==s2[j]) f[pos][j][k][1]=(f[pos^1][j-1][k][1]+f[pos^1][j-1][k-1][0]+f[pos^1][j-1][k-1][1])%mod; else f[pos][j][k][1]=0; } } } out((f[n&1][m][K][0]+f[n&1][m][K][1])%mod); return 0; }