题目概述

 题目链接:点我做题
题解
一、动态规划
  字符串类的题如果要考虑动态规划都可以考虑以什么东西结尾的目标量,比如本题,先定义一个映射
    
     
      
       
        a
       
       
        −
       
       
        0
       
       
        ,
       
       
        e
       
       
        −
       
       
        1
       
       
        ,
       
       
        i
       
       
        −
       
       
        2
       
       
        ,
       
       
        o
       
       
        −
       
       
        3
       
       
        ,
       
       
        u
       
       
        −
       
       
        4
       
      
      
       a-0,e-1,i-2,o-3,u-4
      
     
    a−0,e−1,i−2,o−3,u−4定义
    
     
      
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        j
       
       
        )
       
       
        (
       
       
        j
       
       
        =
       
       
        0
       
       
        ,
       
       
        1
       
       
        ,
       
       
        2
       
       
        ,
       
       
        3
       
       
        ,
       
       
        4
       
       
        )
       
      
      
       f(i,j)(j=0,1,2,3,4)
      
     
    f(i,j)(j=0,1,2,3,4)表示以字符j结尾的长度为i的串在本题规则下的数量,下面我们分析一下规则:
 
   规则一直在告诉我们后面后面,但其实这是一个误导,我们反而应该考虑前面(也应了我们的假设),下面考虑以j结尾的字符前面都有可能有哪些情况:
   以
    
     
      
       
        j
       
       
        =
       
       
        0
       
      
      
       j=0
      
     
    j=0为例,以a结尾的字符,前面可不可以是a呢,不可以,第一条规则说a后面只能跟着e;可不可以是e呢,第二条规则告诉我们可以;前面可不可以是i呢,可以,规则3只规定了i后面不能跟i,其他没有限制;前面可不可以是o呢,不可以,第四条规则规定o后面只能是i或u;前面能不能是u呢,可以,最后一条规则规定u后面只能跟a。
   同理可以把其他字符前面允许的字符规定分析出来:
 
     
      
       
        
         a
        
        
         前
        
        
         :
        
        
         e
        
        
         ,
        
        
         i
        
        
         ,
        
        
         u
        
        
        
         e
        
        
         前
        
        
         :
        
        
         a
        
        
         ,
        
        
         i
        
        
        
         i
        
        
         前
        
        
         :
        
        
         e
        
        
         ,
        
        
         o
        
        
        
         o
        
        
         前
        
        
         :
        
        
         i
        
        
        
         u
        
        
         前
        
        
         :
        
        
         i
        
        
         ,
        
        
         o
        
        
       
       
         a前:e,i,u\\ e前:a,i\\ i前:e,o\\ o前:i\\ u前:i,o\\ 
       
      
     a前:e,i,ue前:a,ii前:e,oo前:iu前:i,o
   长度为i的,以j结尾的串的数量不就等于去掉j字符后,长度为i-1,结尾字符为j字符允许的前缀的字符串的数量嘛,所以有状态转移方程:
 
     
      
       
        
         a
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         0
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         1
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         4
        
        
         )
        
        
        
         e
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         1
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         0
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
        
         i
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         2
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         1
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         3
        
        
         )
        
        
        
         o
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         3
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
        
         u
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         4
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         3
        
        
         )
        
        
       
       
         a:f(i,0)=f(i-1,1)+f(i-1,2)+f(i-1,4)\\ e:f(i,1)=f(i-1,0)+f(i-1,2)\\ i:f(i,2)=f(i-1,1)+f(i-1,3)\\ o:f(i,3)=f(i-1,2)\\ u:f(i,4)=f(i-1,2)+f(i-1,3)\\ 
       
      
     a:f(i,0)=f(i−1,1)+f(i−1,2)+f(i−1,4)e:f(i,1)=f(i−1,0)+f(i−1,2)i:f(i,2)=f(i−1,1)+f(i−1,3)o:f(i,3)=f(i−1,2)u:f(i,4)=f(i−1,2)+f(i−1,3)
   显然有初始条件
    
     
      
       
        f
       
       
        (
       
       
        0
       
       
        ,
       
       
        i
       
       
        )
       
       
        =
       
       
        0
       
      
      
       f(0,i) = 0
      
     
    f(0,i)=0,
    
     
      
       
        f
       
       
        (
       
       
        1
       
       
        ,
       
       
        i
       
       
        )
       
       
        =
       
       
        1
       
      
      
       f(1,i)=1
      
     
    f(1,i)=1
   接下来进行动态规划就可以解决了,用一个二维数组dp储存计算过的状态就可以了,注意题中说的要%
    
     
      
       
        1
       
       
        e
       
       
        9
       
       
        +
       
       
        7
       
      
      
       1e9+7
      
     
    1e9+7
class Solution {
public:
    int countVowelPermutation(int n) 
    {
        vector<vector<long long>> dp(n + 1, vector<long long>(5, 0));
        long long mod = 1e9 + 7;
        for (int i = 0; i < 5; i++)
        {
            dp[1][i] = 1;
        }
        for (int i = 2; i <= n; ++i)
        {
            dp[i][0] = (dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][4]) % mod;
            dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % mod;
            dp[i][2] = (dp[i - 1][1] + dp[i - 1][3]) % mod;
            dp[i][3] = (dp[i - 1][2]) % mod;
            dp[i][4] = (dp[i - 1][2] + dp[i - 1][3]) % mod;
        }
        long long ret = 0;
        for (int i = 0; i < 5; ++i)
        {
            ret += dp[n][i];
        }
        return ret % (mod);
    }
};
 
时间复杂度:
    
     
      
       
        O
       
       
        (
       
       
        C
       
       
        n
       
       
        )
       
      
      
       O(Cn)
      
     
    O(Cn),C为元音字符的个数。
 空间复杂度:本题的状态只和前置状态有关,我们可以只记录上一轮的状态而不必开辟dp数组,所以空间复杂度其实可以优化到O©,C为元音字符个数。
二、矩阵法
  观察我们的状态转移方程:
 
     
      
       
        
         a
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         0
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         1
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         4
        
        
         )
        
        
        
         e
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         1
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         0
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
        
         i
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         2
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         1
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         3
        
        
         )
        
        
        
         o
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         3
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
        
         u
        
        
         :
        
        
         f
        
        
         (
        
        
         i
        
        
         ,
        
        
         4
        
        
         )
        
        
         =
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         2
        
        
         )
        
        
         +
        
        
         f
        
        
         (
        
        
         i
        
        
         −
        
        
         1
        
        
         ,
        
        
         3
        
        
         )
        
        
       
       
         a:f(i,0)=f(i-1,1)+f(i-1,2)+f(i-1,4)\\ e:f(i,1)=f(i-1,0)+f(i-1,2)\\ i:f(i,2)=f(i-1,1)+f(i-1,3)\\ o:f(i,3)=f(i-1,2)\\ u:f(i,4)=f(i-1,2)+f(i-1,3)\\ 
       
      
     a:f(i,0)=f(i−1,1)+f(i−1,2)+f(i−1,4)e:f(i,1)=f(i−1,0)+f(i−1,2)i:f(i,2)=f(i−1,1)+f(i−1,3)o:f(i,3)=f(i−1,2)u:f(i,4)=f(i−1,2)+f(i−1,3)
 若定义向量
    
     
      
       
        
         
          f
         
         
          (
         
         
          i
         
         
          )
         
        
        
         ⃗
        
       
       
        =
       
       
        (
       
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        0
       
       
        )
       
       
        ,
       
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        1
       
       
        )
       
       
        ,
       
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        2
       
       
        )
       
       
        ,
       
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        3
       
       
        )
       
       
        ,
       
       
        f
       
       
        (
       
       
        i
       
       
        ,
       
       
        4
       
       
        )
       
       
        
         )
        
        
         T
        
       
      
      
       \vec{f(i)}=(f(i,0),f(i,1),f(i,2),f(i,3),f(i,4))^{T}
      
     
    f(i)=(f(i,0),f(i,1),f(i,2),f(i,3),f(i,4))T,考虑矩阵知识,状态转移方程可以写为:
 
     
      
       
        
         
          
           f
          
          
           (
          
          
           i
          
          
           )
          
         
         
          ⃗
         
        
        
         =
        
        
         
          [
         
         
          
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
          
          
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
          
          
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
          
          
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
          
         
         
          ]
         
        
        
         
          
           f
          
          
           (
          
          
           i
          
          
           −
          
          
           1
          
          
           )
          
         
         
          ⃗
         
        
        
         =
        
        
         A
        
        
         
          
           f
          
          
           (
          
          
           i
          
          
           −
          
          
           1
          
          
           )
          
         
         
          ⃗
         
        
       
       
         \vec{f(i)}=\begin{bmatrix} 0 & 1&1&0&1 \\ 1 & 0&1&0&0\\ 0&0&1&0&0\\ 0&0&1&1&0\\ \end{bmatrix}\vec{f(i-1)}=A\vec{f(i-1)} 
       
      
     f(i)=⎣⎢⎢⎡01001000111100011000⎦⎥⎥⎤f(i−1)=Af(i−1)
 且
    
     
      
       
        
         
          f
         
         
          (
         
         
          1
         
         
          )
         
        
        
         ⃗
        
       
       
        =
       
       
        (
       
       
        1
       
       
        ,
       
       
        1
       
       
        ,
       
       
        1
       
       
        ,
       
       
        1
       
       
        ,
       
       
        1
       
       
        
         )
        
        
         T
        
       
      
      
       \vec{f(1)}=(1,1,1,1,1)^{T}
      
     
    f(1)=(1,1,1,1,1)T,要得到
    
     
      
       
        
         
          f
         
         
          (
         
         
          n
         
         
          )
         
        
        
         ⃗
        
       
      
      
       \vec{f(n)}
      
     
    f(n)只要让f(1)乘
    
     
      
       
        
         A
        
        
         
          n
         
         
          −
         
         
          1
         
        
       
      
      
       A^{n-1}
      
     
    An−1即可.求矩阵的幂有一些快一点的数学算法,比如快速幂算法可以使用。










