• 求最长公共子串 Longest Common Subsequence


    最长公共子串  // Longest Common Subsequence

    子串有别于子序列, 子串是连续的, 而子序列可以不连续

    /*----------------------------------------------------

    题为求 最长对称子串, 实际可以转化成求最长公共子串
    对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定"Is PAT&TAP symmetric?",最长对称子串为"s PAT&TAP s",于是你应该输出11。
    输入格式:
    输入在一行中给出长度不超过1000的非空字符串。

    输出格式:
    在一行中输出最长对称子串的长度。

    输入样例:
    Is PAT&TAP symmetric?

    输出样例:
    11
    ----------------------------------------------------*/
    // 首先,是最长公共子串,而非子序列.

    // 进而,对称子串,相当于求某个字符串和其逆序的公共子串,到此转化完毕

    我们先看看:最长公共子序列:

    用的是动态规划方法, 用一个表来记录中间过程

    L[i, j]   表示两个字符串a, b    a[0 ~ i], b[0 ~ j] 时的最长公共子序列 

    故而有状态转移方程:

    L[i, j] =
    
      0                    // 某个串的长度为0时
    
      L[i - 1, j - 1] + 1          // a[i] == b[j]
    
      max{L[i, j - 1], L[i - 1, j]}    // a[i] != b[j]

    要特别小心,这里的i, j 是指子序列的长度, 而非你要比较的两个字符串的下标

    所以比较的时候, 要特别处理好,字符串下标和这个子序列长度的对应关系

    同理,对于最长公共子串

    有状态转移方程:

    L[i, j] =
    
      0              // 某个串的长度为0时
    
      0              // a[i] != b[j]
    
      L[i - 1, j - 1] + 1    // a[i] == b[j]

    状态方程如何来? 我以后再补充吧..自己思考一下大致也可以知道

    下面给出这道题的解法, 下面有两种数组下标和串长度的方法!!

    首先你要明白这张表: 0行0列代表串长度为0,那么必然最长公共子串长度为0

    但是如果你直接 i =[ 0,lenA), j = [0,lenB)

    比较 a[i]和b[j], 那么肯定会使得a[0]和b[0]处的错误处理,比如 a[0] == b[0]

    显然暂时最长公共子串长度 = 1

    而你的 L[0, 0] 却统一初始化为0了

    // 第一种方法是统一的,虽然表是从 [0,n]填的,但是使得对应的数组比较也是从a[0, n-1]

    // 第二种方法,是不太统一的,就是单独去处理边界.

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    
    const int EDGE = 1500;
    int x[EDGE][EDGE];
    char a[EDGE];
    int sa;                                     // size of a
    
    int func(){
        memset(x, 0, sizeof(x));
        int i, j, t;
        int maxLen = 0;
        for(i = 1; i <= sa; ++i){        // 0已被初始化,从长度为1开始即可
            for(j = sa - 1, t = 1; t <= sa; --j, ++t){
                if(a[i - 1] == a[j])
             x[i][t]
    = x[i - 1][t - 1] + 1; else  x[i][t] = 0; if(maxLen < x[i][t]) maxLen = x[i][t]; } } return maxLen; } int main(){ // freopen("data.in", "r", stdin); cin.getline(a, 1450); sa = (int)strlen(a); cout<<func(); return 0; }
     1 int func(){
     2     memset(x, 0, sizeof(x));
     3     int i, j, t;
     4     int maxLen = 0;
     5     for(i = 0; i < sa; ++i){
     6         for(j = sa - 1, t = 0; t < sa; --j, ++t){
     7             if(a[i] == a[j]){
     8                 if(i == 0 || t == 0) x[i][t] = 1;
     9                 if(i && t)  x[i][t] = x[i - 1][t - 1] + 1;
    10                 if(x[i][t] > maxLen) maxLen = x[i][t];
    11             }
    12         }
    13     }
    14     return maxLen;
    15 }
    第二种方法
  • 相关阅读:
    VS2008编译出现问题:error C2485: “__restrict”: 无法识别的扩展属性 解决办法
    精度试验结果报告Sleep, GetTickCount, timeGetTime, QueryPerformanceCounter
    error C2872: 'ULONG_PTR' : ambiguous symbol
    无法删除文件:无法读源文件或磁盘”
    如何HOOK桌面窗口消息
    批处理常用特殊符号
    我的Hook学习笔记
    代码注入的三种方法
    Ubuntu 安装 “宋体,微软雅黑,WPS Office的symbol、wingdings、wingdings 2、wingdings 3、webding字体,Consolas雅黑混合版编程字体” 等 Windows 7 下的字体(转)
    Delphi中如何将 Exe 程序或其他资料打包在内,使用时再释放使用(转)
  • 原文地址:https://www.cnblogs.com/Rosebud/p/7154802.html
Copyright © 2020-2023  润新知