普通的LCS是经典的DP问题,那么如果加上方案数,则与最短路计数类似的
1.如果相同,就加上方案数
2.如果可以被更新,就重新统计方案数
但在这一题中,有一种特殊情况要考虑
如果一个子串,(i-1,j)和(i,j-1)都是由(i-1,j-1)转移过来,那么如果在更新f(i,j)时,就不可以用(i-1,j-1)继续累加,就应判定这是重复的,由容斥原理可得,应当减去这一方案数。
例外,此题内存限制严格,需用滚动数组
详细见代码
#include<bits/stdc++.h>
const int mod=1e8;
const int Maxn=5005;
int f[2][Maxn],sum[2][Maxn];
char s1[Maxn],s2[Maxn];
using namespace std;
inline int read(){
char c=getchar();int fh=0;
while(!isdigit(c))c=getchar();
while(isdigit(c))fh=(fh<<1)+(fh<<3)+(c^48),c=getchar();
return fh;
}
int main(){
cin>>s1+1>>s2+1;
int l1=strlen(s1+1)-1,l2=strlen(s2+1)-1;
sum[0][0]=1;
for(int i=1;i<=l2;++i)sum[0][i]=1;//初始化方案数
for(int i=1;i<=l1;++i){
sum[i&1][0]=1;
for(int j=1;j<=l2;++j){
f[i&1][j]=f[(i-1)&1][j];sum[i&1][j]=sum[(i-1)&1][j];//考虑(i-1,j)的情况
if(f[i&1][(j-1)]>f[i&1][j])f[i&1][j]=f[i&1][(j-1)],sum[i&1][j]=sum[i&1][j-1];//i,j-1的情况>就更新
else if(f[i&1][j-1]==f[i&1][j])sum[i&1][j]=(sum[i&1][j]+sum[i&1][j-1])%mod;//=就累加
if(s1[i]==s2[j]){
if(f[i&1][j]<f[(i-1)&1][j-1]+1)f[i&1][j]=f[(i-1)&1][j-1]+1,sum[i&1][j]=sum[(i-1)&1][j-1];
else if(f[i&1][j]==f[(i-1)&1][j-1]+1)sum[i&1][j]=(sum[i&1][j]+sum[(i-1)&1][j-1])%mod;//同理
}
else{
if(f[i&1][j]<f[(i-1)&1][j-1])f[i&1][j]=f[(i-1)&1][j-1],sum[i&1][j]=sum[(i-1)&1][j-1];
else if(f[i&1][j]==f[(i-1)&1][j-1])sum[i&1][j]=(sum[i&1][j]-sum[(i-1)&1][j-1]+mod)%mod;//特殊情况,需要去重
}
}
}
cout<<f[l1&1][l2]<<endl<<sum[l1&1][l2]<<endl;
}