子串sol
阿新 • • 發佈:2020-07-26
子串
字串上的dp
\(f(i,j,k)\)表示將A前i個字元劃分成k段匹配了B中前j個字元的種數
考慮\(f(i,j,k)\)的轉移,不僅有\(f(i-1,j,k)\)
在\(A(i)=B(j)\)時可以由\(f(i-1,j-1,k-1)\)轉移過來
在\(A(i)=B(j)並且A(i-1)=B(j-1)\)時,可以由\(f(i-2,j-2,k-1)\)轉移過來
如果對每一位都找到前面所有可以匹配,較為慢,更高效的方式是用\(sum(i,j,k)\)表示當前可以轉移過來的狀態和,若\(A(i)=B(j)\)則\(sum(i,j,k)=sum(i-1,j-1,k)+f(i-1,j-1,k-1)\)
#include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define mp make_pair #define SZ(x) ((int)x.size()) #define ALL(x) x.begin(),x.end() #define U(i,u) for(register int i=head[u];i;i=nxt[i]) #define rep(i,a,b) for(register int i=(a);i<=(b);++i) #define per(i,a,b) for(register int i=(a);i>=(b);--i) using namespace std; typedef long double ld; typedef long long ll; typedef unsigned int ui; typedef pair<int,int> PII; typedef vector<int> VI; template<class T> inline void read(T &x){ x=0;char c=getchar();int f=1; while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f; } template<class T> inline void cmin(T &x, T y){x=x<y?x:y;} template<class T> inline void cmax(T &x, T y){x=x>y?x:y;} const int N=1001; const int M=201; const int P=1000000007; int n,m,k; char a[N],b[N]; ll f[M][M],sum[M][M]; int main(){ read(n);read(m);read(k);scanf("%s",a+1);scanf("%s",b+1); f[0][0]=1;rep(i,1,n)per(j,m,1)per(t,k,1){ f[j][t]=(f[j][t]+(sum[j][t]=(a[i]==b[j])?sum[j-1][t]+f[j-1][t-1]:0))%P; }printf("%lld\n",f[m][k]); return 0; }