hdu5791php
dp[i][j]表示的是序列A前i個數字和序列B前j個數字的公共子序列的總個數,那麼的dp公式就能夠這麼表示ios
理解一下此公式若最尾部的a[i]和b[j]相等的話,那麼單獨的a[i]和b[j]組成1個相同子序列。spa
同時咱們能夠想一下以前的前i-1個子序列和前j-i個子序列再加上a[i]又能組成dp[i-1]個公共子序列。code
固然了,包含第i個數字的前i個序列a和前j-1個數字的序列b以及包含第j個數字的前j個序列b和前i-1個數字的序列a也要算上。blog
因此把上面3種狀況一合併就是前i-1個子序列a和前j個子序列b的公共子序列個數加上前i個子序列a和前j-1個子序列b的公共子序列個數再加1。get
這裏包含了2倍的dp[i-1][j-1]個數。string
若是a[i]和b[j]不相等的話,減去一個dp[i-1][j-1]個數便可。io
本題中另外一個注意點就是dp[i][j]可能爲負,此時的處理方法是加上一個MODclass
代碼以下:stream
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define MOD 1000000007 5 #define LL long long 6 using namespace std; 7 LL dp[1005][1005]; 8 LL a[1005]; 9 LL b[1005]; 10 int main() 11 { 12 int n,m; 13 while(~scanf("%d%d",&n,&m)) 14 { 15 memset(dp,0,sizeof(dp)); 16 for(int i = 1;i<=n;i++) 17 scanf("%d",&a[i]); 18 for(int j = 1;j<=m;j++) 19 scanf("%d",&b[j]); 20 for(int i = 1;i<=n;i++) 21 { 22 for(int j = 1;j<=m;j++) 23 { 24 if(a[i]==b[j]) 25 dp[i][j]+=dp[i-1][j]+dp[i][j-1]+1; 26 else 27 dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];//極有可能出現負數 28 if(dp[i][j]<0) 29 dp[i][j]+=MOD; 30 dp[i][j]=dp[i][j]%MOD; 31 } 32 } 33 printf("%I64d\n",dp[n][m]); 34 } 35 return 0; 36 }