最长公共子序列针对小字符集的算法

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

但是针对小字符集的情况,可以把复杂度降低到O(n^2),其中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)。

具体实现:

#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];  //next[i][j]????s2?Di????óò±?μúò???‘a‘+j?ú??????£?è?1???óD?íê?l2+1

int main()
{
    scanf("%s%s",s1+1,s2+1);  //s1???ì£?s2??3¤
    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\n",ans);
    return 0;
}
时间: 2024-12-26 11:43:14

最长公共子序列针对小字符集的算法的相关文章

最长公共子序列问题---动态规划

最长递增子序列问题是一个很基本.较常见的小问题,但这个问题的求解方法却并不那么显而易见,需要较深入的思考和较好的算法素养才能得出良好的算法.由于这个问题能运用学过的基本的算法分析和设计的方法与思想,能够锻炼设计较复杂算法的思维,我对这个问题进行了较深入的分析思考,得出了几种复杂度不同算法,并给出了分析和证明. 一,    最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1&l

算法重拾之路——最长公共子序列(LCS)

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第二章:动态规划 最长公共子序列 算法描述: 一个给定序列的子序列是该序列中删去若干元素后得到的序列.确切的说,若给定序列 X={ x1,x2,...,xm },则另一序列 Z = { z1,z2, ... ,zk },是X的子序列是指存在一个严格递增下标序列

最长公共子序列(LCS)

最长公共子序列,英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列.而最长公共子串(要求连续)和最长公共子序列是不同的.       最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的"相似度",即它们的雷同程度,从而能够用来辨别抄袭.对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,

动态规划算法解最长公共子序列LCS问题

第一部分.什么是动态规划算法 ok,咱们先来了解下什么是动态规划算法. 动态规划一般也只能应用于有最优子结构的问题.最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似).简单地说,问题能够分解成子问题来解决. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方式计算最优解的值   //此3步构成动态规划解的基础. 由计算出的结果构造一个最优解.   //此步如果只要求计算最优解的值时,可省略. 好,接下来,咱们

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

LIS LCS 最长上升子序列 最长公共子序列 ...

最长上升子序列,问题定义:http://blog.csdn.net/chenwenshi/article/details/6027086 代码: public static void getData( char[] L ) { int len = L.length; int[] f = new int[len]; String[] res = new String[len]; for( int i = 1; i < len; i++ ) { f[i] = 1; res[i] = "&quo

最长递增子序列 &amp;&amp; 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方

P3402 最长公共子序列(nlogn)

P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: 给定两个长度分别为n和m的序列,序列中的每个元素都是正整数.保证每个序列中的各个元素互不相同.求这两个序列的最长公共子序列的长度. DJL最讨厌重复劳动,所以不想做那些做过的题.于是他找你来帮他做作业. 输入输出格式 输入格式: 第一行两个整数n和m,表示两个数列的

HDU 1243 反恐训练营 (动态规划求最长公共子序列)

反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3040    Accepted Submission(s): 693 Problem Description 当今国际反恐形势很严峻,特别是美国"9.11事件"以后,国际恐怖势力更是有恃无恐,制造了多起骇人听闻的恐怖事件.基于此,各国都十分担心恐怖势力会对本国社会造