Given an integer n
, your task is to count how many strings of length n
can be formed under the following rules:
- Each character is a lower case vowel (
'a'
,'e'
,'i'
,'o'
,'u'
) - Each vowel
'a'
may only be followed by an'e'
. - Each vowel
'e'
may only be followed by an'a'
or an'i'
. - Each vowel
'i'
may not be followed by another'i'
. - Each vowel
'o'
may only be followed by an'i'
or a'u'
. - Each vowel
'u'
may only be followed by an'a'.
Since the answer may be too large, return it modulo 10^9 + 7.
Example 1:
Input: n = 1 Output: 5 Explanation: All possible strings are: "a", "e", "i" , "o" and "u".
Example 2:
Input: n = 2 Output: 10 Explanation: All possible strings are: "ae", "ea", "ei", "ia", "ie", "io", "iu", "oi", "ou" and "ua".
Example 3:
Input: n = 5 Output: 68
Constraints:
1 <= n <= 2 * 10^4
思路:
一开始觉得这题跟图有关,后来发现好像不太好算结果,就改用dp, 其实确定了方法,这题不麻烦,只是心里没底, 提交上去会不会超时。整体是这样的, 创建一个二维数组dp, dp[i]是一个长度为5的整数数组,dp[i][j]代表某个元音字母(a, e, i, o, u)在第i位上的计数。这样我们可以推导出下面的结论(字母与index的对应为a: 0, e: 1, i: 2, o: 3, u: 4):
能排在a之前的只有e, i, u, 所以dp[i][0] = dp[i-1][1] + dp[i-1][2] + dp[i-1][4]
能排在e之前的只有a, i, 所以dp[i][1] = dp[i-1][0] + dp[i-1][2]
能排在i之前的只有i, o, 所以dp[i][2] = dp[i-1][1] + dp[i-1][3]
能排在o之前的只有i, 所以dp[i][3] = dp[i-1][2]
能排在u之前的只有i, o, 所以dp[i][4] = dp[i-1][2] + dp[i-1][3]
代码:
const M: i64 = 1000000007;
impl Solution {
fn dp(n: usize, visited: &mut Vec<bool>, cache: &mut Vec<Vec<i64>>) -> Vec<i64> {
if n == 0 {
return vec![1, 1, 1, 1, 1];
}
if visited[n - 1] {
let prev = cache[n - 1].clone();
cache[n][0] = (prev[1] + prev[2] + prev[4]) % M;
cache[n][1] = (prev[0] + prev[2]) % M;
cache[n][2] = (prev[1] + prev[3]) % M;
cache[n][3] = prev[2] % M;
cache[n][4] = (prev[2] + prev[3]) % M;
visited[n] = true;
return cache[n].clone();
} else {
let prev = Solution::dp(n - 1, visited, cache);
cache[n][0] = (prev[1] + prev[2] + prev[4]) % M;
cache[n][1] = (prev[0] + prev[2]) % M;
cache[n][2] = (prev[1] + prev[3]) % M;
cache[n][3] = prev[2] % M;
cache[n][4] = (prev[2] + prev[3]) % M;
visited[n] = true;
return cache[n].clone();
}
}
pub fn count_vowel_permutation(n: i32) -> i32 {
let mut visited = vec![false; n as usize];
let mut cache = vec![vec![0; 5]; n as usize];
let l = Solution::dp(n as usize - 1, &mut visited, &mut cache);
(l.into_iter().sum::<i64>() % M) as i32
}
}