洛谷P2516 [HAOI2010]最长公共子序列
动态规划 容斥原理
这一题求LCS 就用 n^2 动态规划做
求方案数 用到的是与容斥原理差不多的方法
因为f[ i ][ j ] = f[ i-1 ][ j-1] + 1 if == 所以方案数 加上 c[ i-1 ][ j-1 ] 但是也有可能
i j 位匹配了,但是 可能在 i-1 j 或 i j-1 时 就已经 有这样的长度的匹配
所以如果也可行的话也要加上
然后 if != f[ i ][ j ] = max(f[ i-1 ][ j ],f[ i ][ j-1 ])
然后我们就 如果 两个中一个 == [i][j] 那就加上对应的 c[ i ][ j-1 ]或
如果c[i-1][j-1] 也能转到 要减去 因为 [i-1][j-1] 可以同时被 [i-1][j] 和 [i][j-1] 转移到
这样就被算到了两次 所以要减去 ,但是为什么不dfs下去 ,因为这是顺序枚举的 ,前面的已经去掉了影响
所以就不用了
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std ; 10 11 const int maxn = 5011,MOD = 100000000 ; 12 char a[maxn],b[maxn] ; 13 int i,j,n,now,cur,m ; 14 int f[2][maxn],ct[2][maxn] ; 15 16 int main() 17 { 18 scanf("%s",a+1) ; scanf("%s",b+1) ; 19 n = strlen(a+1) -1 ; m = strlen(b+1) -1 ; 20 for(i=1;i<=n;i++) 21 { 22 now^=1 ; 23 //for(j=1;j<=m;j++) f[now][j] = 0 ,ct[now][j] = 0 ; 24 for(j=1;j<=m;j++) 25 if(a[ i ]==b[ j ]) 26 { 27 f[ now ][ j ] = f[ cur ][ j-1 ] + 1 ; 28 ct[ now ][ j ] =( ct[cur][j-1] % MOD 29 + (f[cur][j]==f[now][j])*ct[cur][j] %MOD 30 + (f[now][j-1]==f[now][j])*ct[now][j-1] % MOD ) % MOD ; 31 if(!f[cur][j-1]) ct[now][j]++ ; // 32 } 33 else 34 { 35 f[ now ][ j ] = max( f[ now ][ j-1 ],f[ cur ][ j ] ) ; 36 ct[ now ][ j ] =( ( -(f[cur][j-1]==f[now][j]) )*ct[cur][j-1] % MOD 37 + (f[cur][j]==f[now][j])*ct[cur][j] %MOD 38 + (f[now][j-1]==f[now][j])*ct[now][j-1] % MOD + MOD ) % MOD ; 39 } 40 cur^=1 ; 41 } 42 printf("%d %d ",f[now][m],ct[now][m]) ; 43 44 return 0 ; 45 }