2016级算法第四次上机-E.Bamboo and the Ancient Spell

Bamboo and the Ancient Spell

分析

可能英文读题难度比较大,但是只要看到全大写的 "THE LONGEST COMMON SUBSEQUENCE !"应该就清楚这是考什么的了。
最长公共子序列:可以不连续。序列长度很大时,暴力方法非常费时,这也是一道比较经典的《算法导论》上的动态规划题。

设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:
若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。

核心
c[i,j] = c[i,j]=0 (if i=0 or j=0)
c[i,j] = c[i-1,j-1]+1(i,j>0 and xi=yj)
c[i,j] = max(c[i,j-1],c[i-1,j])(i,j>0 and xi!=yj)

特别:# ?

对#的处理方式:删除;替换;条件判断
?:比较相等的时候加上等于?的条件

其中删除:string自带的erase等函数、或者for循环。都要注意字符串长度的变化

代码如下:

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
string s1,s2;
int c[150][150];
int main()
{
    while(cin>>s1>>s2)
    {
        int len1 = s1.length();
        int len2 = s2.length();
        memset(c,0,sizeof(c));

        for(int i = 1;i<=len1;i++)
            for(int j = 1;j<=len2;j++)
        {
            if(s1[i-1]!='#'&&s2[j-1]!='#'&&(s1[i-1]==s2[j-1]||s1[i-1]=='?'||s2[j-1]=='?'))
                c[i][j]=c[i-1][j-1]+1;
            else c[i][j]=max(c[i-1][j],c[i][j-1]);
        }

        printf("%d
",c[len1][len2]);
    }
}

附一个简单char数组删除#的代码:

void prepro()
{
    int i,j;
    for(i = 1; s1[i]!=''; i++)
        if(s1[i]=='#')
        {
            for(j=i; s1[j]!=''; j++)
                s1[j]=s1[j+1];
            i--;
        }
    for(i = 1; s2[i]!=''; i++)
        if(s2[i]=='#')
        {
            for(j=i; s2[j]!=''; j++)
                s2[j]=s2[j+1];
            i--;
        }
}
原文地址:https://www.cnblogs.com/AlvinZH/p/7978012.html