zoukankan      html  css  js  c++  java
  • 最长公共子序列针对小字符集的算法

    一般对于两个字符串,长度分别为n和m,其时间复杂度为O(nm)。

    但是针对小字符集的情况,可以把复杂度降低到O(n^2+km),其中n为两个字符串较短的长度。这种方法对于两个字符串长度相差很大的情况比O(nm)要优化很多。

    就假设所有的字符都是小写字母,这样就符合小字符集的前提了。设较短的字符串为S1,较长的字符串为S2。字符串下标从1开始。

    S2字符串每个位置右边第一个字符是可以通过O(km)预处理得到的。其中k为小字符集的字符个数,m为较长的那个字符串的长度。

    用next[i][j]表示S2[i]右边第一个(char)('a'+j)的位置。

    设dp[i][j]表示S1匹配了前i位,长度为j的最长公共子序列与S2匹配到的最靠左的位置。如果不存在则为length(S2)+1。

    dp[i][0] = 0

    如果S2的dp[i-1][j-1]这个位置右边第一个与S1[i]相等的位置存在,那么dp[i][j] = min{ dp[i-1][j], next[dp[i-1][j-1]][S1[i]] }。

    否则dp[i][j] = dp[i-1][j]。

    对于每一个不是-1的dp,记录下j,最后取一个最大就是最长公共子序列了。

    因此,总的复杂度为O(n^2+km)。

    具体实现:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const int maxn=1005;
    const int maxm=1000005;
    char s1[maxn],s2[maxm];
    int dp[maxn][maxn];
    int next[maxm][26]; 
    
    int main()
    {
        scanf("%s%s",s1+1,s2+1);  
        int l1=strlen(s1+1);
        int l2=strlen(s2+1);
        for (int i=0;i<maxm;i++)
            for (int j=0;j<26;j++)
                next[i][j]=l2+1;
        for (int i=0;i<maxn;i++)
            for (int j=0;j<maxn;j++)
                dp[i][j]=l2+1;
        for (int i=l2-1;i>=0;i--)
        {
            for (int j=0;j<26;j++)
            {
                char cc='a'+j;
                if (s2[i+1]==cc) next[i][j]=i+1;
                else next[i][j]=next[i+1][j];
            }
        }
        for (int i=1;i<=l1;i++) dp[i][0]=0;
        int ans=0;
        for (int i=1;i<=l1;i++)
        {
            for (int j=1;j<=i;j++)
            {
                if (next[dp[i-1][j-1]][s1[i]-'a']!=l2+1) dp[i][j]=min(dp[i-1][j],next[dp[i-1][j-1]][s1[i]-'a']);
                else dp[i][j]=dp[i-1][j];
                if (dp[i][j]!=l2+1) ans=max(ans,j);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    CI工具Jenkins的安装配置【linux】——jenkins集成sonarqube-异常解决
    高可用架构,期刊下载
    struct
    Fragment与Activity相互传递值
    Android ble (蓝牙低功耗)使用注意事项(转)
    Android ble蓝牙问题(转)
    Android-BlutoothBle,蓝牙中心设备(peripheral)向外围设备(GattServer)连续写入多个Characteristic的注意事项
    Android滑动导航菜单TabLayout+ViewPager+Fragment
    Material Design:TabLayout的使用
    Android-BLE蓝牙原理
  • 原文地址:https://www.cnblogs.com/acmsong/p/8157326.html
Copyright © 2011-2022 走看看