最小会问代价课程设计报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1.实验题目
最小回文代价问题:回文是指一个对称的字符串,代表这个串从左往右读和从右往左读是一样的。

给定一个字符串,往其中插入最少的字符,得到一个回文串,求最小插入字符数。

提示: 计算原字符串与逆序字符串LCS(最长公共子序列长度),用字符串长度减去LCS 长度。

2.问题分析
本程序要求实现给定一个字符串,往其中插入最少的字符,得到一个回文串,求出最小插入字符数。

程序所能达到的:给定一个字符串,求出将其变成回文插入的最小字符数。

完成这些问题需要解决的关键问题是求出原字符串与逆字符串的LCS(最长公共子序列长度)。

①数据的输入形式和输入值的范围:输入一个字符串且以回车键结束输入,在所有的输入中,元素的值都是字符型。

②结果的输出形式:输出最小插入字符数。

③测试数据:
A.a
B.acba
C.qwert
3.数据结构的选择和概要设计
数据结构:数组
概要设计:1)为了实现上述功能,需要:①定义两个字符型数组s[M],rs[N]分别来存放原字符串与逆置字符串②设置一个矩阵记录原字符串与逆置符串的匹配情况,并返回矩阵中最大元素 lcs[row][col]③当字符匹配的时候,不是简单的给相应元素赋上1,而是赋上其左上角元素的值加1。

④我们用两个标记变量row和col来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的长度就求出来了。

⑤在屏幕上显示操作菜单2)本程序包含的3个函数
①主函数main()
②求LCS函数length()
③逆置字符串函数reverse()
各函数间的关系如下:
length
main
reverse
4.算法思想
计算原字符串与逆序字符串的LCS(最长公共子序列长度),用原字符串长度减去LCS 长度,结果便是最小插入字符的个数。

故本题的关键是求出LCS:设置一个矩阵,记录两个字符串的匹配情况。

当字符匹配的时候,给相应元素赋上其左上角元素的值加1。

我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么等到矩阵完成的时候,最长匹配子串的位置和长度就求出来了。

5.详细设计和主要编码段
本程序的关键问题是求出原字符串与逆字符串的最长公共子序列长度,用原字符串长度减去LCS长度。

设置一个二维数组lcs[M][N]记录原字符串与逆字符串的匹配情况,当原字符串与逆字符串匹配的时候,给相应元素赋上其左上角元素的值加1,即lcs[i][j] = lcs[i - 1][j - 1] + 1。

我们用两个标记变量row和col来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么等到矩阵完成的时候,即可求出矩阵中最大元素lcs[row][col]。

1)主函数
void main()
{
char s[M],rs[N];
int lenth;
printf("请输入一个字符串(回车键结束):\n");
scanf("%s", s);
reverse(s, rs);
lenth= length(s, rs);
printf("最小插入字符数是:%d\n", strlen(s)-lenth);
}
2)逆置字符串函数
void reverse(char* s, char* rs)
{
char *p=s;
while(*p)
++p;
while(--p>=s){
*rs=*p;
*rs++;
}
*rs=0;
}
3)求LCS函数
int length( char *s, char *rs) {
int i, j;
int lcs[M][N];
int row, col;
row=strlen(s);
col=strlen(rs);
for(i=0; i<M; i++)
for(j=0; j<N; j++)
lcs[i][j]=0;
for(i=1;i<=row;i++) {
for(j=1;j<=col;j++) {
if(s[i-1]==rs[j-1]) {
lcs[i][j]=lcs[i-1][j-1]+1;
}
else
{
if(lcs[i-1][j]>=lcs[i][j-1]) {
lcs[i][j]=lcs[i-1][j];
}
else {
lcs[i][j] = lcs[i][j-1];
}
}
}
}
return lcs[row][col];
}
6.上机调试情况记录
本程序使用的数据结构是数组,再求LCS时算法中,当字符匹配的时候,不是简单的给相应元素赋上1,而是赋上其左上角元素的值加1,程序得到简化,语句少而精炼。

所以出现的语法问题主要在于子函数和一些变量的定义,括号的配对,关键字和函数名称的书写,以及一些库函数的规范使用,这些问题可根据编译器的警告提示一一解决。

7.测试用例、结果及其算法性能分析
A:a
B:acba
C:qwert
算法性能分析:时间复杂度○(row*col)
7.用户使用说明
本程序运行过程中带有提示性语句,如下图,用户只需根据提示进行操作即可。

9.参考文献
[1] 王昆仑,李红. 数据结构与算法. 北京:中国铁道出版社,2006年5月
[2] 何钦铭,颜晖. C语言程序设计. 北京:高等教育出版社,2008年1月
10.附录(完整源程序)
/*给定一个字符串,往其中插入最少的字符,得到一个回文串,求最小插入字符数。

*/ //提示: 计算原字符串与逆序字符串LCS(最长公共子序列长度),用字符串长度减去LCS长度。

#include <stdio.h>
#include <string.h>
#define M 100
#define N 100
/*求最长公共子序列的长度*/
int length( char *s, char *rs) {
int i, j;
int lcs[M][N];//定义一个二维数组,记录原字符串与逆置符串的匹配情况
int row, col;
row=strlen(s);//定义行下标变量记录源字符串的长度
col=strlen(rs);//定义列下标变量记录逆置字符串的长度
for(i=0; i<M; i++)//矩阵的初始化
for(j=0; j<N; j++)
lcs[i][j]=0;
/*对原字符串与逆置符串匹配*/
for(i=1;i<=row;i++) {
for(j=1;j<=col;j++) {
if(s[i-1]==rs[j-1]) {//当字符匹配的时候,赋上其左上角元素的值加1
lcs[i][j]=lcs[i-1][j-1]+1;
}
else
{
if(lcs[i-1][j]>=lcs[i][j-1]) {
lcs[i][j]=lcs[i-1][j];
}
else {
lcs[i][j] = lcs[i][j-1];
}
}
}
}
return lcs[row][col];//返回矩阵中最大元素的位置,即LCS
}
/*原字符串的逆置*/
void reverse(char* s, char* rs)
{
char *p=s; //定义指针变量p指向原字符串的首地址
while(*p)
++p;
while(--p>=s){
*rs=*p;
*rs++;
}
*rs=0;
}
/*主函数*/
void main()
{
char s[M],rs[N];
int lenth;//定义变量接收最长公共子序列长度
printf("请输入一个字符串(回车键结束):\n");
scanf("%s", s);
reverse(s, rs);//调用逆置字符串函数
lenth= length(s, rs);
printf("最小插入字符数是:%d\n", strlen(s)-lenth);//求出最小插入字符数}。

相关文档
最新文档