zoukankan      html  css  js  c++  java
  • 算法编程题积累(3)——腾讯笔试"构造回文“问题

    首先理解题意,回文串的特点:倒序后跟原串相同。故而可以将原串看成向一个回文串在任意位置添加任意字符后形成的字符串,也就是说原串中存在一段未必连续的回文序列

    通过分析可以知道AC本题的核心思路:求出回文序列的长度,用原串的长度减去其长度即可

    要求出回文序列的长度,肯定要利用回文串的特点,故而想到求原串和其反串的最长公共子序列(不一定连续)。

    所以可以采用文本比较算法中的Needleman/Wunsch算法(动态规划思想):

    定义:

      LCS(A,B)表示字符串A和字符串B的最长公共子串的长度。很显然,LSC(A,B)=0表示两个字符串没有公共部分。

      Rev(A)表示反转字符串A

      Len(A)表示字符串A的长度

      A+B表示连接字符串A和字符串B

      性质:

      LCS(A,A)=Len(A)

      LCS(A,"")=0

      LCS(A,B)=LCS(B,A)

      0≤LCS(A,B)≤Min(Len(A),Len(B))

      LCS(A,B)=LCS(Rev(A),Rev(B))

      LCS(A+C,B+C)=LCS(A,B)+Len(C)

      LCS(A+B,A+C)=Len(A)+LCS(B,C)

      LCS(A,B)≥LCS(A,C)+LCS(B,C)

      LCS(A+C,B)≥LCS(A,B)+LCS(B,C)

      为了讲解计算LCS(A,B),特给予以下几个定义

      A=a1a2……aN,表示A是由a1a2……aN这N个字符组成,Len(A)=N

      B=b1b2……bM,表示B是由b1b2……bM这M个字符组成,Len(B)=M

      定义LCS(i,j)=LCS(a1a2……ai,b1b2……bj),其中0≤i≤N,0≤j≤M

      故:  LCS(N,M)=LCS(A,B)

          LCS(0,0)=0

          LCS(0,j)=0

          LCS(i,0)=0

      对于1≤i≤N,1≤j≤M,有公式一

      若ai=bj,则LCS(i,j)=LCS(i-1,j-1)+1

      若ai≠bj,则LCS(i,j)=Max(LCS(i-1,j-1),LCS(i-1,j),LCS(i,j-1))=Max(LCS(i-1,j),LCS(i,j-1))

      计算LCS(A,B)的算法有很多,下面介绍的Needleman/Wunsch算法是其中的一种。和LD算法类似,Needleman/Wunsch算法用的都是动态规划的思想。在Needleman/Wunsch算法中还设定了一个权值,用以区分三种操作(插入、删除、更改)的优先级。在下面的算法中,认为三种操作的优先级都一样。故权值默认为1。

      

      举例说明:A=GGATCGA,B=GAATTCAGTTA,计算LCS(A,B)

      第一步:初始化LCS矩阵

    Needleman/Wunsch算法矩阵
      GAATTCAGTTA
      0 0 0 0 0 0 0 0 0 0 0 0
    G 0                      
    G 0                      
    A 0                      
    T 0                      
    C 0                      
    G 0                      
    A 0                      

      第二步:利用公式一,计算矩阵的第一行

    Needleman/Wunsch算法矩阵
      GAATTCAGTTA
      0 0 0 0 0 0 0 0 0 0 0 0
    G 0 1 1 1 1 1 1 1 1 1 1 1
    G 0                      
    A 0                      
    T 0                      
    C 0                      
    G 0                      
    A 0                      

       第三步:利用公式一,计算矩阵的其余各行

    Needleman/Wunsch算法矩阵
      GAATTCAGTTA
      0 0 0 0 0 0 0 0 0 0 0 0
    G 0 1 1 1 1 1 1 1 1 1 1 1
    G 0 1 1 1 1 1 1 1 2 2 2 2
    A 0 1 2 2 2 2 2 2 2 2 2 2
    T 0 1 2 2 3 3 3 3 3 3 3 3
    C 0 1 2 2 3 3 4 4 4 4 4 4
    G 0 1 2 2 3 3 3 4 5 5 5 5
    A 0 1 2 3 3 3 3 4 5 5 5 6

      则,LCS(A,B)=LCS(7,11)=6

    --------------------------------------------------我是分割线---------------------------------------------------------------

    AC代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define MAX 1100
     4 
     5 int LCS[MAX][MAX];
     6 string s1, s2;
     7 int i, j;
     8 int maxOfAll(int a, int b, int c)
     9 {
    10     return max(max(a, b), c);
    11 }
    12 
    13 int main()
    14 {
    15     while(cin >> s2)
    16     {
    17         s1 = s2;
    18         size_t len = s1.length();
    19         for(int ix = 0; ix <= len; ++ix)
    20             LCS[ix][0] = LCS[0][ix] = 0;
    21         reverse(s2.begin(), s2.end());
    22 
    23         for(i = 1; i <= len; ++i)
    24         {
    25             for(j = 1; j <= len; ++j)
    26             {
    27                 if(s1[i-1] == s2[j-1])
    28                     LCS[i][j] = LCS[i-1][j-1] + 1;
    29                 else
    30                     LCS[i][j] = maxOfAll(LCS[i-1][j], LCS[i-1][j-1], LCS[i][j-1]);
    31             }
    32 
    33         }
    34         cout << len-LCS[len][len] << endl;
    35     }
    36 }
     1 import java.util.*;
     2 
     3 public class Main {
     4     public static void main(String[] args) {
     5         Scanner sc = new Scanner(System.in);
     6         while(sc.hasNext()) {
     7             String s1 = sc.next();
     8             String s2 = new StringBuffer(s1).reverse().toString();
     9             int [][] dp = new int[s1.length()+1][s2.length()+1];
    10             for (int i = 1; i < dp.length; ++i) {
    11                 for (int j = 1; j < dp[0].length; ++j) {
    12                     dp[i][j] = s1.charAt(i-1) == s2.charAt(j-1) ? dp[i-1][j-1] + 1 : Math.max(dp[i-1][j], dp[i][j-1]);
    13                 }
    14             }
    15             System.out.println(s1.length() - dp[s1.length()][s2.length()]);
    16         }
    17         sc.close();
    18     }
    19 }
  • 相关阅读:
    【原创】阿里云 ECS 腾讯云CVM(云服务器)网站搭建教程 + PHP+MYSQL环境搭建教程
    50+慕课收费资源下载
    王雨的jquery练习01---显示隐藏列表
    王雨的JavaScript练习06---js实现动画效果(2)
    王雨的JavaScript练习05---js实现动画效果(1)
    王雨的JavaScript练习04---DOM操作CSS
    王雨的JavaScript练习03---Ajax初体验
    王雨的JavaScript练习02---复习DOM,充实文档内容
    王雨的JavaScript练习01---js幻灯(纯手打)
    目前最高清C值解析接口!还有各类VIP接口![9.09]
  • 原文地址:https://www.cnblogs.com/socrates-lzstu/p/6721795.html
Copyright © 2011-2022 走看看