KMP

转自:http://blog.csdn.net/amazing7/article/details/51671545

1.概述

  KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

  给定两个字符串T和W,长度分别为m和n,判断W是否在T中出现,如果出现则返回出现的位置。常规方法是遍历T的每一个位置,然后从该位置开始和W进行匹配,但是这种方法的复杂度是O(mn)。kmp算法通过一个O(n)的预处理,使匹配的复杂度降为O(m+n)。

2.思路

这里写图片描述

我们要在 
字符串T=“ABCDABCDABDE”中查找 
字符串W="ABCDABD"出现的位置。

这里写图片描述

  很明显可以看出前6位都是匹配的,然而第7位不匹配,一般的做法就是从T[i](i从1到9)开始和W开始循环比较。直到i=4,也就是图2,比较成功返回下标4。

这里写图片描述

  这样比较无异效率很低,然而我们发现在字符串”ABCDAB”之中有两个”AB”,第一次比较失败之后,又循环比较了四次,把W字符串从第一个”AB”的位置移动到了第二个”AB”处(显然这四次比较毫无意义)。于是Knuth、Morris、Pratt这三个人就想了个办法去掉了这些无意义的比较。

  然而是怎么实现的呢?就要从W字符串的部分匹配值(相等的前缀和后缀)说起。

2.1部分匹配值

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"前缀"</span>指除了最后一个字符以外,一个字符串的全部头部组合;
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"后缀"</span>指除了第一个字符以外,一个字符串的全部尾部组合。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

  “部分匹配值”就是”前缀”和”后缀”的最长的共有元素的长度。以W字符串”ABCDABD”为例:

“A”的前缀和后缀都为空集,共有元素的长度为0;

“AB”的前缀为[A],后缀为[B],共有元素的长度为0; 

“ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0; 

“ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

“ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;

“ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;

“ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

从上面我们就得出了字符串W的部分匹配表:

这里写图片描述 

我们把部分匹配表存放在一个next[]数组中,那部分匹配值究竟怎么用呢? 
我们可以根据部分匹配值计算出向后移动的位数,避免了一位位的比较:

移动位数 = 已匹配的字符数 - 对应的部分匹配值

以图1中为例:

 前6位已经匹配(已匹配的字符数 =6); 
 next[5] = 2 (对应的部分匹配值 = 2)
  
我们可以得出移动位数为 6-2=4位。

   可以看出next数组的作用,就是在我们匹配失败的时候,确定我们子串需要往后移动的距离,而避免我们的主串指针进行回退。这样可以保证主串在只遍历一遍的情况下找到子串。因此KMP算法的重点就是如何快速的求出这个next数组。

2.2 求next数组

  next数组是只与子串有关与主串无关的,它记录的是子串到每个字符处那个公共前缀(或后缀)的最大长度。

这里写图片描述

   假设我们已经求出的next[i-1] = j,即W从0到i-1处这段字符串中,最大的相等的前缀和后缀长度为j。 
   那如何求得next[i]呢?

这是后就要分为两种情况了:

①、如果W[i]==W[j]

  显然前缀往后再加上一个字符之后依然会和后缀往后加上一个字符相等,此时

next[i] = next[i-1] + 1,即next[i] = j+1

②、如果W[i]!=W[j]

  那么 W[0-i]这段字符串 中,最大的相等的前缀和后缀的长度必然小于等于j。 (以前是j,现在加了一个不同字符,所以不可能大于j)。

  从上面的W字符串的前缀分析可以看出,短字符串的前缀必是长字符串前缀的子集

  既然长的匹配值不行了,我们只能回溯到短的匹配。把j下标循环向前(下标0方向)移动,直到W[j]==W[i]或者j==0为止(回到第一种情况)。

  那么j怎么移动呢?当前W[i]!=W[j],那么就求0到j-1的最长匹配值(next[j - 1]),再比较这个最长匹配串的末尾字符的下一位是否等于w[i],不相等再循环。 
   
上代码:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] <span class="hljs-title" style="box-sizing: border-box;">getNextArray</span>(String s){  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] ch = s.toCharArray();
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i,j;
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] next = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[ch.length];  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < ch.length; i++){  
               <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(j > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> && ch[i] != ch[j]){   
                   j = next[j - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//j <next[j - 1],所以向前移动</span>
               }
               <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(ch[i] == ch[j]){  
                   j++;  
               }  
               next[i] = j;  
           }  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> next;  
       } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

W字符串”ABCDABD”为例,运行结果如下:

这里写图片描述

3.KMP

  其实进行next数组求解的过程,类似于主串和子串进行匹配的过程,只不过是在next数组求解过程中,是子串和子串自己进行比较而已。 

因此整个KMP算法的代码过程如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
      *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> str1 被匹配的字符串
      *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> str2  子串
      *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> 布尔值
      */</span>
     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">kmp</span>(String str1,String str2){  
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] strA = str1.toCharArray();  
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] strB = str2.toCharArray();  
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] next = getNextArray(str2);  
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i,j;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里i是从0开始的</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < strA.length; i++){  
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(j > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> && strA[i] != strB[j])  
                    j = next[j-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];  
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(strA[i] == strB[j]){  
                    j++;  
                }  
               <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//匹配成功</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(j == strB.length){  
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;  
                }  
            }  
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;  
        } 
     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] <span class="hljs-title" style="box-sizing: border-box;">getNextArray</span>(String s){  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>[] ch = s.toCharArray();
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i,j;
           <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//数组初始全部为0,所以next[0]=0</span>
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] next = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[ch.length];  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < ch.length; i++){  
               <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(j > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> && ch[i] != ch[j]){   
                   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//j <next[j - 1],所以向前移动</span>
                   j = next[j - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];    
               }
               <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(ch[i] == ch[j]){  
                   j++;  
               }  
               next[i] = j;  
           }  
           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> next;  
       } 
     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {
          String T =<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ABCDABCDABDE"</span>;
          String W = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ABCDABD"</span>;
              System.out.println(kmp(T,W));
         }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li></ul>

运行结果:

这里写图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值