552. Student Attendance Record II
作者:互联网
比较难的dp问题。由于A最多出现一次,我们先不考虑A,只考虑存在L和P的情况,最后插入A。
dp[i][0] 前i个且最后为L,dp[i][1] 前i个且最后为P
递推公式如下
dp[i][0] 说明当前最后是L,那么前面可能是L或者A。前面如果是L,那么再前面只能是A,所以是 dp[i-2][1];如果前面是A,就是 dp[i-1][1]。
所以 dp[i][0] = dp[i-1][1] + dp[i-2][1]
dp[i][1] = dp[i-1][0] + dp[i-1][1],没什么特别的,因为如果最后是A,前面是什么都可以。
Base Case
dp[1][0]=dp[1][1]=1; dp[2][0]=dp[2][1]=2;
我们定义 dp[0][0]=0,dp[0][1]=1,最后循环插入A的时候会更加方便,同时 dp[2][0]也可以包括在dp的循环中。
至此,如果给定长度为i,那么不包含A的所有可能字符串的总数为 dp[i][0]+dp[i][1]
最后的答案包含两种情况:
1. 不包含A,dp[n][0]+dp[n][1]
2. 包含A,由于只能有一个A,A可以出现在任何位置。用一个循环枚举A的位置,左边总数*右边总数即可,(dp[i][0]+dp[i][1]) * (dp[n-1-i][0]+dp[n-1-i][1])
由于base case里 dp[0][0]=0,dp[0][1]=1,因此 dp[0][0]+dp[0][1]=1,i=0和n-1的边界条件也包括了进去。
class Solution { public: long long MOD = 1e9 + 7; int checkRecord(int n) { vector<vector<long long>> dp(n+1,vector<long long>(2,0)); // there is no absent dp[0][0]=0; dp[1][0]=1; dp[0][1]=1; dp[1][1]=1; for (int i=2;i<=n;++i){ dp[i][0] = (dp[i-1][1] + dp[i-2][1]) % MOD; dp[i][1] = (dp[i-1][0] + dp[i-1][1]) % MOD; } long long res=dp[n][0]+dp[n][1]; // Absent at different position for (int i=0;i<n;++i){ res = (res + (dp[i][0]+dp[i][1]) * (dp[n-1-i][0]+dp[n-1-i][1])) % MOD; } return res; } };
时间复杂度 O(n)
空间复杂度 O(n)
Reference
https://www.cnblogs.com/seyjs/p/10420247.html
标签:Attendance,包含,前面,int,最后,II,Record,vector,dp 来源: https://www.cnblogs.com/hankunyan/p/11463106.html