CodeForces 682D Alyona and Strings
$dp$,最长公共子序列变形。
$f[i][j][h][0]$表示:$s[1 \cdots i]$与$t[1 \cdots j]$,分成了$k$段,并且$s[i]$与$t[j]$之后没有切的最优解。
$f[i][j][h][1]$表示:$s[1 \cdots i]$与$t[1 \cdots j]$,分成了$k$段,并且$s[i]$与$t[j]$之后切了一段的最优解。
$f[i][j][h][0]$可以从$f[i-1][j][h][0]$,$f[i-1][j][h][1]$,$f[i][j-1][h][0]$,$f[i][j-1][h][1]$转移过来。
如果$s[i]=t[j]$,$f[i][j][h][1]$就可以从$f[i-1][j-1][h-1][0]$和$f[i-1][j-1][h-1][1]$转移过来。
如果$s[i]=t[j]$并且$s[i-1]=t[j-1]$,$f[i][j][h][1]$还可以从$f[i-1][j-1][h][1]$转移过来。
大致和最长公共子序列过程相似。时间复杂度$O(n*m*k)$。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-6; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } const int maxn=1010; char s[maxn],t[maxn]; int n,m,k,f[maxn][maxn][13][2]; int main() { scanf("%d%d%d",&n,&m,&k); scanf("%s%s",s+1,t+1); s[0]='.'; t[0]=','; memset(f,-1,sizeof f); for(int i=0; i<=n; i++) for(int j=0; j<=m; j++) f[i][j][0][0]=f[i][j][0][1]=0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { for(int h=1; h<=k; h++) { if(s[i]==t[j]) { if(s[i-1]==t[j-1]&&f[i-1][j-1][h][1]!=-1) f[i][j][h][1]=max(f[i][j][h][1],f[i-1][j-1][h][1]+1); if(f[i-1][j-1][h-1][0]!=-1) f[i][j][h][1]=max(f[i][j][h][1],f[i-1][j-1][h-1][0]+1); if(f[i-1][j-1][h-1][1]!=-1) f[i][j][h][1]=max(f[i][j][h][1],f[i-1][j-1][h-1][1]+1); } f[i][j][h][0]=max(f[i][j][h][0],f[i-1][j][h][0]); f[i][j][h][0]=max(f[i][j][h][0],f[i][j-1][h][0]); f[i][j][h][0]=max(f[i][j][h][0],f[i-1][j][h][1]); f[i][j][h][0]=max(f[i][j][h][0],f[i][j-1][h][1]); } } } int ans=0; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) ans=max(ans,f[i][j][k][0]),ans=max(ans,f[i][j][k][1]); printf("%d\n",ans); return 0; }