Link: https://leetcode.com/problems/decremental-string-concatenation/description/
## 思路
三维dp
dp[i][j][k]表示把i后面包含i的所有word逐个加在 以j开头 以k结尾的string上得到的string的最短的长度
python里面用了```@lru_cache(None)```就会自动把dp array存下来
#### 优化
参考[这里](https://leetcode.com/problems/decremental-string-concatenation/solutions/3677609/dp/)
由于我们知道每个dfs在运算的时候 拿到的start和end肯定有一个来自上一个字符串
因此我们只需要记录另一个字符是什么 以及他在start还是end即可
## Code
Python $O(26*26n)$
```python=
class Solution:
def minimizeConcatenatedLength(self, words: List[str]) -> int:
@lru_cache(None)
def dfs(idx, start, end):
if idx>=len(words): return 0
addToBack = dfs(idx+1, start, ord(words[idx][-1])-ord('a'))
if (ord(words[idx][0])-ord('a'))==end: addToBack -= 1
addToFront = dfs(idx+1, ord(words[idx][0])-ord('a'), end)
if (ord(words[idx][-1])-ord('a'))==start: addToFront -= 1
return min(addToBack, addToFront)+len(words[idx])
return len(words[0])+dfs(1, ord(words[0][0])-ord('a'), ord(words[0][-1])-ord('a'))
```
Java $O(26*26n)$
```java=
class Solution {
public int minimizeConcatenatedLength(String[] words) {
int[][][] dp = new int[1001][26][26];
return words[0].length()+dfs(1, words[0].charAt(0)-'a', words[0].charAt(words[0].length()-1)-'a', words, dp);
}
public int dfs(int idx, int start, int end, String[] words, int[][][] dp){
if (idx>=words.length) return 0;
if (dp[idx][start][end]==0){
int n = words[idx].length();
int addToBack = dfs(idx+1, start, words[idx].charAt(n-1)-'a', words, dp);
if((words[idx].charAt(0)-'a')==end) addToBack -= 1;
int addToFront = dfs(idx+1, words[idx].charAt(0)-'a', end, words, dp);
if((words[idx].charAt(n-1)-'a')==start) addToFront -= 1;
dp[idx][start][end] = Math.min(addToBack, addToFront)+words[idx].length();
}
return dp[idx][start][end];
}
}
```
Java $O(26*2*n)$
```java=
class Solution {
public int minimizeConcatenatedLength(String[] words) {
int[][][] dp = new int[1001][26][2];
return words[0].length()+dfs(1, words[0].charAt(0)-'a', true, words, dp);
}
public int dfs(int idx, int ch, boolean left, String[] words, int[][][] dp){
if (idx>=words.length) return 0;
if (dp[idx][ch][left?1:0]==0){
int n = words[idx].length();
int start = left ? ch : (words[idx-1].charAt(0)-'a');
int end = !left ? ch : (words[idx-1].charAt(words[idx-1].length()-1)-'a');
int addToBack = dfs(idx+1, start, true, words, dp);
if((words[idx].charAt(0)-'a')==end) addToBack -= 1;
int addToFront = dfs(idx+1, end, false, words, dp);
if((words[idx].charAt(n-1)-'a')==start) addToFront -= 1;
dp[idx][ch][left?1:0] = Math.min(addToBack, addToFront)+words[idx].length();
}
return dp[idx][ch][left?1:0];
}
}
```