《算法分析与设计》练习8

目录

A 解密

B 最长公共子序列问题(LCS)之备忘录法

C 最长公共子序列问题(LCS)之动态规划

D 最长公共子序列问题(LCS)--构造LCS

E 牛牛的字符串

F 最大字段和


A 解密

题目描述

湖南中医药大学有含浦、东塘 2 个校区,学校办学历史悠久,前身为 1934 年的湖南国医专科学校,1953

年创办湖南中医进修学校,1960 年创建普通高等本科院校——湖南中医学院,1979 年成为全国首批取得

中医类研究生学历教育资格的院校,1990 年原湖南科技大学成建制并入湖南中医学院,2002 年与湖南省

中医药研究院合并,2006 年经教育部批准更名为湖南中医药大学,2012 年进入湖南省一本招生序列。

目前,学校与湖南省中医药研究院实行校院合一的管理体制。学校学科门类齐全、中医药特色鲜明。学校

设有 18 个学院、24 个本科专业,涵盖医、理、工、管、文等 5 大学科门类。中医诊断学在本学科研究领

域居国内领先水平。

小 F 居住在含浦校区,他想和东塘校区的同学小 L 聊天,为了保证沟通安全,他发明了一种加密方式,这

种加密方式是这样的:对于一个 01 串,小 F 会将其从左到右每 8 位分成一组,最后一组可能不足 8 位,

对每组进行逆序操作,即如果原来是 bLbL+1bL+2 · · · bR−1bR, 逆序之后变成 bRbR−1bR−2 · · · bL−1bL。现在

小 F 已经加密好了一个串,并且将其发给了小 L,你能帮助小 L 得到这串密文对应的原始信息吗?

输入

单组数据。

一行一个 01 串,代表加密后的字符串,串长度大于 0, 小于等于 100。

输出

一行字符串,代表加密后的字符串所对应的原始信。

样例输入 Copy

100010110011101

样例输出 Copy

110100011011100

分析:这题分两步走,第一步对前面的每八个字符进行逆行输出

                                 第二步 对剩下不足八个字符的进行逆行输出

代码实现:c语言

#include <stdio.h>

#include <stdlib.h>



int main (){

char a[200];

while(~scanf("%s",a)){

    int n=strlen(a);

    solve(a,n);

    for(int i=0;i<n;i++)

        printf("%c",a[i]);

    printf("\n");

}

return 0;

}



void solve(char a[],int n){

    int count=0;

    int x=n/8;

    int y=n%8;

    int j;

for(int i=0;i<n;i++){

    if((i+1)%8==0)

    {

        nixu(a,i-7,i);

        count++;

        j=i;

    }

    if(count==x)   break;

}



nixu(a,j+1,n-1);

}



void nixu(char a[],int p,int q)

{

         int mid=(p+q)/2;

    for(int i=p;i<=mid;i++)

        swap(a,i,q--);



}



void swap(char a[],int i,int j)

{

    char temp=a[i];

    a[i]=a[j];

    a[j]=temp;

}

B 最长公共子序列问题(LCS)之备忘录法

题目描述

使用备忘录法求解两个序列的最长公共子序列的长度。

输入

每组输入包括两行,每行包括一个字符串。

输出

两个序列的最长公共子序列的长度。

样例输入 Copy

ACBCDABD

ABDCABA

样例输出 Copy

5

分析:根据题目分析得,按照常理,我们比较最大公共子串时,总是喜欢把相同的去掉,不同的就比较下一位。

          用计算机来表示时,假如有a, b 两个字符串,我们从字符串的最后一位比较。记  tb[i][j] 表示最大公共字串的数目。

          if   a[i] ==b[j] 我们就 可以  tb[i][j]=tb[i-1][j-1]+1;

          if   a[i]!=b[j]  我们就 可以  计数剩下最大的tb, 用式子表示 就是  : max( tb[i-1][j]  ,   tb[i][j-1] );

           意思就是 像我们平时计数一样,不一样了,就丢掉其中一个字符串的这一位,让另一个字符串的该位去与之比较。

          可能有点抽象,举例子:样例输入的例子。

          第一步:我们比较 第一行的最后一位 D 和 第二行的最后一位 A

         不相等,怎么办呢。

         看第二步: 我们可以丢掉D,让A 与剩下的比较 如 :与B。

                           我们也可以丢掉A, 让 D ;与剩下的比较 如: 与B。

         以此类推........

代码分析:c语言

#include <stdio.h>

#include <stdlib.h>



int bwl[200][200];

int main (){

char a[200];

char b[200];

while(~scanf("%s",a)){

    scanf("%s",b);

    int al=strlen(a);

    int bl=strlen(b);

    int z=solve(a,b,al,bl);

    printf("%d",z);

    printf("\n");



}



return 0;

}





int solve (char a[],char b[],int al,int bl){

    if(al==0||bl==0) return 0;

    if(bwl[al-1][bl-1]>0) return bwl[al-1][bl-1];

    if(a[al-1]==b[bl-1]) {

        bwl[al-1][bl-1]=solve(a,b,al-1,bl-1)+1;

        return bwl[al-1][bl-1];

    }

    else  {

        int v1=solve(a,b,al-1,bl);

        int v2=solve(a,b,al,bl-1);

        bwl[al-1][bl-1]=max(v1,v2);

        return bwl[al-1][bl-1];

    }

}





int max(int x,int y){

return x>y?x:y;



}

C 最长公共子序列问题(LCS)之动态规划

题目描述

使用动态规划算法求解两个序列的最长公共子序列的长度。

输入

每组输入包括两行,每行包括一个字符串。

输出

两个序列的最长公共子序列的长度。

样例输入 Copy

ACBCDABD

ABDCABA

样例输出 Copy

5

分析:根据上题,意思懂了就行,方法不同而已,动态规化就是填一张表就行

从第一行第一列开始填,填到最后一行最后一列

代码实现:c语言

#include <stdio.h>

#include <stdlib.h>



int tb[200][200];

int bb[200][200];



int main (){

char a[200];

char b[200];

while(~scanf("%s",a)){

    scanf("%s",b);

    int al=strlen(a);

    int bl=strlen(b);

    int z=solve(a,b,al,bl);

    printf("%d",z);

    printf("\n");

}





return 0;

}



int solve(char a[],char b[],int al,int bl){

    int x=al;

    int y=bl;

   for(int i=0;i<=x;i++)

     tb[i][0]=0;

   for(int j=0;j<=y;j++)

    tb[0][j]=0;



   for(int i=1;i<=x;i++)

    for(int j=1;j<=y;j++)

   {

       if(a[i-1]==b[j-1])

       {

           tb[i][j]=tb[i-1][j-1]+1;

           bb[i][j]=1;

       }

       else{

        if(tb[i][j-1]>tb[i-1][j])

        {

            tb[i][j]=tb[i][j-1];

            bb[i][j]=2;

        }

        else{

            tb[i][j]=tb[i-1][j];

            bb[i][j]=3;

        }



       }

   }

return tb[x][y];

}

D 最长公共子序列问题(LCS)--构造LCS

题目描述

使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。

输入

每组输入包括两行,每行包括一个字符串。

输出

两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)

样例输入 Copy

acdbxx

ccdxx

样例输出 Copy

cdxx

分析:此题就在上一题的基础上,把相等的字符找出来即可。

代码实现:c语言

#include <stdio.h>

#include <stdlib.h>



int tb[200][200];

int bb[200][200];



int main (){

char a[200];

char b[200];

while(~scanf("%s",a)){

    scanf("%s",b);

    int al=strlen(a);

    int bl=strlen(b);

    int z=solve(a,b,al,bl);

    traceback(a,al,bl);

    printf("\n");

}





return 0;

}



int solve(char a[],char b[],int al,int bl){

    int x=al;

    int y=bl;

   for(int i=0;i<=x;i++)

     tb[i][0]=0;

   for(int j=0;j<=y;j++)

    tb[0][j]=0;



   for(int i=1;i<=x;i++)

    for(int j=1;j<=y;j++)

   {

       if(a[i-1]==b[j-1])

       {

           tb[i][j]=tb[i-1][j-1]+1;

           bb[i][j]=1;

       }

       else{

        if(tb[i][j-1]>tb[i-1][j])

        {

            tb[i][j]=tb[i][j-1];

            bb[i][j]=2;

        }

        else{

            tb[i][j]=tb[i-1][j];

            bb[i][j]=3;

        }



       }

   }

return tb[x][y];

}



void traceback(char a[],int i,int j){

    if(i==0||j==0) return;

       if(bb[i][j]==1) {

            traceback(a,i-1,j-1);

        printf("%c",a[i-1]);

       }

       else{

        if(bb[i][j]==2) traceback(a,i,j-1);

        else traceback(a,i-1,j);

       }



}

E 牛牛的字符串

题目描述

牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。

输入

每组数据包括两行,每行为一个字符串。

输出

输出最长的公共连续子串的长度。

样例输入 Copy

abede

abgde

样例输出 Copy

2

分析:应该采用动态规划来做,就是填一张表。

怎么填表呢?只要相等,就左上角加1 ,否则就 填0。

然后输出表中最大值即可。

具体请看代码:

代码实现:c语言

#include <stdio.h>

#include <stdlib.h>



int tb[200][200];

int main (){

char a[200];

char b[200];

while(~scanf("%s",a)){

    scanf("%s",b);

    int al=strlen(a);

    int bl=strlen(b);

    int z=solve(a,b,al,bl);

    printf("%d",z);

    printf("\n");

}





return 0;

}





int solve(char a[],char b[],int al,int bl) {

    int x=al;

    int y=bl;

for(int i=0;i<=x;i++)

    tb[i][0]=0;

for(int j=0;j<=y;j++)

    tb[0][j]=0;



    int max=0;



for(int i=1;i<=x;i++)

    for(int j=1;j<=y;j++)

{

    if(a[i-1]==b[j-1]) tb[i][j]=tb[i-1][j-1]+1;

    else tb[i][j]=0;

    if(max<tb[i][j])

        max=tb[i][j];

}



return max;

}

F 最大字段和

题目描述

给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。

输入

每组输入包括两行,第一行为序列长度n,第二行为序列。

输出

输出字段和的最大值。

样例输入 Copy

5

-1 0 1 2 3

样例输出 Copy

6

分析:最大字段和其实也有规律,也可以画一张表就可以得出解

只不过只需要一维数组即可。

怎么填表呢?  先填 b[0]=a[0],

在填 b[i]  (i>=1)。 if  b[i-1] <0  ,直接填 b[i] =a[i];

                                   if  b[i-1]>0  ,就填  b[i]=a[i]+b[i-1];

填完表,只需拿最大值即可。

代码实现:c语言

#include <stdio.h>

#include <stdlib.h>



int b[200];

int main (){

int a[200];

int n;

while(~scanf("%d",&n)){

    for(int i=0;i<n;i++)

        scanf("%d",&a[i]);

    int z=solve(a,n);

    printf("%d",z);

    printf("\n");

}



return 0;

}





int solve(int a[],int n){

b[0]=a[0];

int max=b[0];

for(int i=1;i<n;i++)

{

    if(b[i-1]<0) b[i]=a[i];

    else b[i]=a[i]+b[i-1];

    if(max<b[i])

        max=b[i];

}



return max;

}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值