小明思考

          Just a software engineer
          posts - 124, comments - 36, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
          問題給定兩個(gè)字符串S和T,計(jì)算S的子序列為T的個(gè)數(shù)。

          這里的字符串的子序列指的是刪除字符串的幾個(gè)字符(也可以不刪)而得到的新的字符串,但是不能改變字符的相對(duì)位置。

          比如“ACE”是“ABCDE”的子序列,但是“AEC”就不是。

          如果S=“rabbbit” T=“rabit”,有3種不同的子序列為T的構(gòu)成方法,那么結(jié)果應(yīng)該返回3。

          分析:

          解法一:遞歸
          直覺的解法是使用遞歸,先在S中找到T的第一個(gè)字符,然后遞歸查找在剩余的S查找剩余的T(除去首字符)。
          如果T的長(zhǎng)度為1,只需要計(jì)算S中一共有幾個(gè)T就可以了。
          代碼如下,非常簡(jiǎn)潔,但是效率不高:

          public int numDistinct(String S, String T) {
                  int ls = S.length();
                  int lt = T.length();
                  if(ls<lt){
                      return 0;
                  }
                  
                  char[] cs = S.toCharArray();
                  char t0 = T.charAt(0);
                  String T1 = T.substring(1);
                  
                  int result = 0;
                  for(int i=0;i<ls;++i){
                      if(cs[i]==t0){
                          if(lt>1){
                              result += numDistinct(S.substring(i+1),T1);
                          }
                          else{
                              ++result;
                          }
                      }    
                  }
                  return result;
              }

          解法二,
          為了提高效率,很自然的想法是使用動(dòng)態(tài)規(guī)劃,記錄中間狀態(tài),從而避免重復(fù)計(jì)數(shù)。

          狀態(tài)轉(zhuǎn)移方程如下,計(jì)D(m,n)為S的子串(0..m)中子序列為T(0..n)的個(gè)數(shù)。

          那么D(m,n) = D(m-1,n) if S(m)<>T(n)
                           = D(m-1,n)+D(m-1,n-1) if (S(m)=T(n) and n>0)
                           = D(m-1,n)+1 if(S(m)=T(0) and n=0)

          代碼如下:復(fù)雜度為O(mn) m,n為S和T的長(zhǎng)度

          public int numDistinct(String S, String T) {
                  int ls = S.length();
                  int lt = T.length();
                  if(ls<lt){
                      return 0;
                  }
                  
                  int[][] memo = new int[ls][lt];
                  char[] cs = S.toCharArray();
                  char[] ct = T.toCharArray();
                  
                  memo[0] = new int[lt];
                  memo[0][0]= (cs[0]==ct[0])?1:0;
                  
                  for(int i=1;i<ls;++i){
                      int[] mprev = memo[i-1];
                      int[] m = memo[i] = new int[lt];
                      char s = cs[i];
                      for(int j=0;j<lt;++j){
                          char t = ct[j];
                          m[j] = mprev[j];
                          if(s==t){
                              m[j] += ((j==0)?1:mprev[j-1]);
                          }
                      }
                  }
                  return memo[ls-1][lt-1];
              }

          評(píng)論

          # re: 子序列計(jì)數(shù)  回復(fù)  更多評(píng)論   

          2013-06-12 23:56 by 初學(xué)者:阿古

          7.字符串String str = “ABCDEABCDABC”;定義一個(gè)方法query,8.該方法算出該字符串中每一個(gè)字符的個(gè)數(shù),9.打印格式如:
          A——3
          B——3
          C——3
          D——2
          E——1
          主站蜘蛛池模板: 三穗县| 抚州市| 华宁县| 平定县| 凤冈县| 曲松县| 汉源县| 苏尼特右旗| 卢氏县| 永丰县| 丰城市| 株洲市| 武陟县| 涞水县| 黄山市| 涪陵区| 榆社县| 金门县| 景泰县| 灵石县| 栖霞市| 大竹县| 深州市| 芒康县| 巴里| 清徐县| 桃园市| 宁强县| 江津市| 四平市| 永善县| 碌曲县| 清新县| 汝城县| 仙桃市| 随州市| 清涧县| 安康市| 房产| 蒙城县| 彭阳县|