---
# System prepended metadata

title: DP

---

# DP 


一個由小問題推到大問題的演算算

## 費氏數列

### 純遞迴版
```cpp=
int fib(int N) {
	if( N == 1 || N == 0 ) return 1;
	return fib(N-1)+fib(N-2);
}
```


```graphviz

digraph {
	a[label="4"]
	b[label="3"]
	c[label="2"]
	d[label="1"]
	e[label="0"]
	a -> b[color=red]
	b -> c[color=red]
	c -> d[color=red]
	c -> e[color=red]
	
	d -> c[label="1", color=green]
	e -> c[label="1", color=green]
	c -> b[label="2", color=green]
	
	f[label="1"]
	b->f[color=red]
	f->b[label="1", color=green]
	
	b->a[label="3", color=green]
	
	
	g[label="2"]
	a->g[color=red]
	
	h[label="1"]
	g->h[color=red]
	h->g[label="1", color=green]
	
	i[label="0"]
	g->i[color=red]
	i->g[label="1", color=green]
	
	
	g->a[label="2", color=green]
}
```




$$時空複雜度O(\phi^N)$$



### 動態規劃版

```cpp=
int save[mxN]; //mxN==100000
save[0] = save[1] = 1;
int fib(int N) {
	if( save[N] ) return save[N]; //if( save[N] != 0 )
	else {
		save[N] = fib(N-1)+fib(N-2);
		return save[N];
	}
}
```

```graphviz
digraph {
	"4" -> "3"
	"3" -> "2"
	"2" -> "1"
	"1" -> "2"[label=1, color=green]
	"2" -> "0"
	"0" -> "2"[label=1, color=green]
	"2" -> "3"[label=2, color=green]
	"3" -> "4"[label=3, color=green]
	"4"->"2"
	"2"->"4"[label=2, color=green]
}
```

$$時空複雜度O(N)$$

### 迭代版

```cpp=
int dp[mxN]; //mxN=100
dp[0] = dp[1] = 1;
for( int i = 2; i < mxN; ++i ){
	dp[i] = dp[i-1] + dp[i-2];
}
```

$$時空複雜度O(N)$$

<font color = white>

$$$$

</font>

###  最常共同子序列

$a \, =\,accd$
$b \, =\,adcc$
$dp[i][j] \implies a字串取到第i個,b自串取到第j個時的LCS$
{
$$
dp[i][j] = \begin{cases}
	dp[i-1][j-1]+1\quad &if \quad a_i = b_j \\
	max( dp[i][j-1], dp[i-1][j]) \quad  &else
\end{cases}
$$
}

把下方code中註釋掉的那兩行拔掉即可

###  最常連續共同子序列

$a \, =\,accd$
$b \, =\,adcc$
$dp[i][j] \implies a字串取到第i個,b自串取到第j個時的LCS$
{
$$dp[i][j] = \begin{cases}
	dp[i-1][j-1]+1\quad &if \quad a_i = b_j \\
\end{cases}$$
}

```cpp=
constexpr int mxN = 100002;
int dp[2][mxN];
void solve(string &s1, string &s2) {
	memset( dp, 0, sizeof(dp));
	s1 = "+"+s1; // + has no mean
	s2 = "+"+s2;
	const int s1_len = s1.size(), s2_len = s2.size();
	int mx = 0;
	for( int i = 1; i < s1_len; ++i) {
		for( int j = 1; j < s2_len; ++j ){
			if( s1[i] == s2[j] )
				dp[i&1][j] = dp[~i&1][j-1]+1;	 //i&1 i%2, ~i&1 (i+1)%2
			else 
				dp[i&1][j] = 0;
			mx = max( dp[i&1][j], mx);
			//else  [with no continue]
			//	dp[i&1][j] = max( dp[i&1][j-1], dp[~i&1][j] );
		}
		//for( int _ = 1; _ < s2_len; _++ ) cout << dp[i&1][_] << ' ';
		//cout << endl;
	}
	cout << mx << '\n';
}
```

