洛谷P2516 [HAOI2010]最长公共子序列 动态规划 容斥原理

洛谷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 }
原文地址:https://www.cnblogs.com/third2333/p/7068576.html