目录
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;
}