‘壹’ 如何使用C语言求解最长公共子字符串问题及相关的算法
假定字符串采用堆分配方式,编写一个程序,求两个字符串S和T的一个最长公共子串
本题的思路:
本题要实现的算法扫描两个字符串。其中index指出最长公共子串在s中的序号,length指出最长公共子串的长度
堆分配存储表示如下:
typedef struct{
char *ch;
int length;
}Hstring;
Status MaxComString(Hstring S,Hstring T,int &length){
index=0;
length=0;
i=0;
//令i作为扫描字符串S的指针
while(i<S.length){
j=0;
//令j作为扫描字符串T的指针
while(j<T.length){
if(s.ch[i]==T.ch[j]){
//找一个子串,其在字符串S中的序号为i,长度为length1
length1=i;
for(k=1;S.ch[i+k]==T.ch[j+k];k++)length1++;
if(length1>length){
//将较大长度值赋给index与length
index=i;
length=length1;
}
j=j+length1;//继续扫描字符串T中第j=length1个字符之后的字符
}else{
j++;
}
}//while
i++;
}//while
printf("最长公共子串:");
for(i=0;i<length;i++)printf("%c",S.ch[index+i]);
return OK;
}
‘贰’ C语言实现最长公共子串与最长公共子序列
给定两个字符串s1="GeeksforGeeks",s2="GeeksQuizGo",则它们的最长公共子串为“Geeks”,长度为5。
运用动态规划的思想,将两个字符串映射为一张二维表,表格中的值代表到当前为止的最长公共子串的值,如下图所示:
生成这张表的步骤(假设这张表为t[][], r为行标,c为列标):
Code
整个算法的时间复杂度为O(len1 * len2),len1与len2分别为两个字符串的长度。
最长公共子序列与最长公共子串的区别是,最长公共子序列不要求“连续匹配”,它的目的是找到两个字符串中最大的公共部分。依然以s1="GeeksforGeeks",s2="GeeksQuizGo"为例,它们的最长公共子序列为“Geekso”和“GeeksG”,长度为6。
它的二维表如下所示:
它的生成步骤与最长公共子序列的最大不同在第3步,最长公共子序列在遇到s1[r] != s2[c]情况时,不会将t[r][c]重置为0,而是选择Max(t[r-1][c], t[r][c-1])作为新值,即它一直保存着前面已比较序列的最长公共序列值。
‘叁’ 求最长公共子序列的C语言程序
得到字符串m1,m2后,有一个为空则子列为空。
如果都不为空,开始下面的步骤。
求得两列的长度分别为n1,n2。
动态生n2行n1列矩阵(二维数组)。
取m2中每个元素(记位置为i)与m1中元素(记位置为j)逐个比较,如果相等则为矩阵中相应行列坐标的元素赋值为1,否则为0(可用循环嵌套完成)。
比如m1(abc0cbad)m2(cba1abc)两串的话,可以得到如图所示矩阵。
然后,不难看出,要进行如下步骤。
定义max,用来记录最大子列中元素个数。
定义数组l[n2],用来记录最大子列的首字符地址(因为可能有不同最大子列,故用数组,而不是单个变量)。
判断矩阵中每一个元素,是否为1,如果是则记下此时行地址到l数组,然后判断相对于这个元素的下一行下一列的元素是否为1,如果是则继续判断,一直到为0。记下此次判断(即一个while循环)中“1”的个数n,存入变量max。
对于矩阵中的每一个元素都这么判断,如果判断中n的值大于max那么把n付给max,同时把这个子列的首地址付给l[0],l[0]后面的元素全赋值为-1。如果,某次判断得到的n与max相同,即有相同最大子列,那么把它的首地址存入l数组的下一个位置。
当这个矩阵的每一个元素都判断完毕后,会得到max,和数组l,然后用循环做如下输出过程:依次以l数组中的每个元素为首地址,输出m2字符串中以相应序号开头的max个字符,那么完成所有最大子列的输出。
昨天失眠了,一直到今天凌晨3点多,脑袋浑浑噩噩的,本想帮你敲代码,可是脑力不支了,估计敲出来也乱,还有问题的话,再讨论452032545
‘肆’ C语言求最长子序列
下面是你的代码修改过后的结果,改过的地方都有注释,另有测试样例。
#include <stdio.h>
/*
5
5
-2 5 4 -7 3
最长子序列:9
4
-2 -3 8 -7
最长子序列:8
3
-2 -2 7
最长子序列:7
2
-1 5
最长子序列:5
1
-2
最长子序列:0
Process returned 0 (0x0) execution time : 30.999 s
Press any key to continue.
*/
int main() {
int count, i, k, a[100] = {0}, b[10000] = {0}, n, num, max = 0, q, m, j;
scanf("%d", &n);
for (count = 0; count < n; count++) {
scanf("%d", &num);
for (i = 0; i < num; i++) scanf("%d", &a[i]);
k = 0;
for (i = 0; i < num; i++)
for (q = 1; q < num + 1; q++) {
for (m = i; (m < i + q) && (m < num); m++) //在这里再加一个判断条件(m < num),
b[k] += a[m];
k++;
}
j = k - 1;
max = 0; //如果全部都是负数的话,结果应该是0,即一个都不选
for (; j >= 0; j--)
if (max < b[j]) max = b[j];
printf("最长子序列:%d\n", max);
max = 0;
for (i = 0; i < 10000; i++) b[i] = 0;
}
return 0;
}
‘伍’ 最长 公共子序列问题(算法分析 C++)
#include <iostream>
#include <string>
using namespace std;
//主函数
int main()
{
int m,n;
char *x,*y;
int **b,**c;
void LCSLength(int m,int n,char *y,char *x,int **c,int **b);
void LCS(int i,int j,char *x,int**b);
cout<<"请输入两个序列的长度:"<<endl;
cin>>m>>n;
x=new char[m];
y=new char[n];
cout<<"请输入两个序列:"<<endl;
cin>>x>>y;
b=new int *[m + 1]; // 注意这里,原式没有+1
for (int i=0;i<=m;i++)
b[i]=new int[n + 1]; // 注意这里,原式没有+1
c=new int *[m + 1];
for (int j=0;j<=m;j++)
c[j]=new int[n + 1]; // 注意这里,原式没有+1
LCSLength(m,n,x,y,c,b);
cout<<"最长公共子序列的元素个数为"<<c[m][n]<<endl;
cout<<"该序列为:";
LCS(m,n,x,b); //注意后面的内容是清理,暂时先跳过去,你先搞定主程序先
/* delete []x;
delete []y;
for(int k=0;k<=m;k++)
delete []b[k];
delete []b;
for(int h=0;h<=m;h++)
delete []c[h];
delete []c;
*/
return 0;
}
//计算最优值
void LCSLength(int m,int n,char *y,char *x,int **c,int **b)
{
int i,j;
for(i=1;i<=m;i++)c[i][0]=0;
for(j=0;j<=n;j++)c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(x[i]==y[j]){c[i][j]=c[i-1][j-1]+1;b[i][j]=1;}
else if(c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];b[i][j]=2;}
else {c[i][j]=c[i][j-1];b[i][j]=3;}
}
}
//构造最长公共子序列
void LCS(int i,int j,char *x,int**b)
{
if(i==0||j==0)return;
if(b[i][j]==1){LCS(i-1,j-1,x,b);cout<<x[i];}
else if(b[i][j]==2)LCS(i-1,j,x,b);
else LCS(i,j-1,x,b);
}
‘陆’ 求一个最长公共子序列的 C++代码
#include <iostream.h>
#include <iomanip.h>
#define MAX 99
//typedef char MM;
void main()
{ int i,j,m,n,h=0;
char x[MAX]={ ' ', ' '},y[MAX]={ ' ', ' '},b[MAX][MAX]={ ' '};
int c[MAX][MAX]={0};
char temp[MAX]={ ' '};
cout < < "**本程序可以求得字符数在99以内的任意两个字符串的最大公共子序列**\n ";
cout < < "请输入第一个字符串的长度m= ";
cin> > m;
cout < < "请输入第一个字符串(“回车”结束)\n如果输入的字符数超过m,则会出错!\nx[ " < <m < < "]= ";
for(i=1;i <=m;i++)
cin> > x[i]; //键盘输入x和y
cout < < "请输入第二个字符串的长度n= ";
cin> > n;
cout < < "请输入第二个字符串\ny[ " < <n < < "]= ";
for(i=1;i <=n;i++)
cin> > y[i];
for(i=1;i <=m;i++)c[i][0]=0; //动态规划开始
for(i=1;i <=n;i++)c[0][i]=0;
for(i=1;i <=m;i++)
for(j=1;j <=n;j++)
{if(x[i]==y[j])
{c[i][j]=c[i-1][j-1]+1;
b[i][j]= '\\ ';
}else
if(c[i-1][j]> =c[i][j-1])
{ c[i][j]=c[i-1][j];
b[i][j]= '│ ';
}else{c[i][j]=c[i][j-1];
b[i][j]= '- ';
}
} //动态规划结束
cout < < "c[m][n]中的内容:\n ";
for(i=0;i <=m;i++)
{for(j=0;j <=n;j++)
cout < <c[i][j];
cout < <endl;
}
cout < < "b[m][n]中的内容:\n ";
for(i=1;i <=m;i++)
{for(j=1;j <=n;j++)
cout < <b[i][j];
cout < <endl;
}
i=m,j=n;
while(1)
{if(i==0││j==0) break;
if(b[i][j]== '\\ '){
temp[h++]=x[i]; //反序记录最长公共子序列到temp中
i=i-1,j=j-1;
}
else
if(b[i][j]== '│ ')
i=i-1;
else
j=j-1;}
cout < < "\nx[ " < <m < < "]和y[ " < <n < < "]的最长公共子序列为: ";
for(i=h-1;i> =0;i--) //格式化输出最长公共子序列
if(i==h-1)
if(h==1)
cout < < "LCS: < " < <temp[i] < < "> ";
else
cout < < "LCS: < " < <temp[i];
else
if(i==0)
cout < < ", " < <temp[i] < < "> ";
else
cout < < ", " < <temp[i];
cout < < "\n " < <endl;
}
‘柒’ 求一个最长公共自序列的程序,C语言的,拜托了
#include<stdio.h>
void LCSLength(int m,int n,char *x,char *y,int c[8][7],int b[8][7])
{
int i,j;
for(i=0;i<m;i++) c[i][0]=0;
for(i=0;i<n;i++) c[0][i]=0;
for(i=1;i<m;i++){
for(j=1;j<n;j++){
if(x[i]==y[j]){
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}else if(c[i-1][j]>=c[i][j-1]){
c[i][j]=c[i-1][j];
b[i][j]=2;
}else {
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
}
void printMatrix(int matrix[8][7]){
int i,j;
for(i=0;i<8;i++){
for(j=0;j<7;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
}
void LCS(int i,int j,char *x,int b[8][7] )
{
if(i==0||j==0) return;
if(b[i][j]==1){
LCS(i-1,j-1,x,b);
printf("%c\n",x[i]);
}else if(b[i][j]==2){
LCS(i-1,j,x,b);
}else{
LCS(i,j-1,x,b);
}
}
int main()
{
int c[8][7]={{0}};
int b[8][7]={{0}};
char X[8]={' ','A','B','C','B','D','A','B'};
char Y[7]={' ','B','D','C','A','B','A'};
LCSLength(8,7,X,Y,c,b);
printf("Matrix c\n");
printMatrix(c);
printf("Matrix b\n");
printMatrix(b);
printf("最大公共子序列长度为%d\n",c[7][6]);
LCS(7,6,X,b);
return 1;
}
‘捌’ C语言 最长的连续的公共子序列
#include<stdio.h>
#define M 7
#define N 7
int c[M][N];
int b[M][N];
int lcsLength(char x[],char y[])
{
int m=M-1;
int n=N-1;
int i,j;
for(i=0;i<M;i++)
c[i][0]=0;
for(j=0;j<N;j++)
c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(x[i]==x[j])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
return c[m][n];
}
void lcs(int i,int j,char x[],int b[M][N])
{
if(i==0||j==0)
return;
if(b[i][j]==1)
{
lcs(i-1,j-1,x,b);
printf("%-c,%d\t",x[i],i);
}
else if(b[i][j]==2)
lcs(i-1,j,x,b);
else
lcs(i,j-1,x,b);
}
void main()
{
char x[]={'0','A','B','C','B','D','A'};
char y[]={'0','B','H','C','A','B','A'};
int i,j;
printf("%d\n",lcsLength(x,y));
printf("\n");
lcs(M-1,N-1,x,b);
}
‘玖’ (算法 c++)动态规划法求解最长公共子序列 本人菜鸟求高手改错帮忙完成 谢谢了
不是我不想帮你,但如果真要改的话,整个程序差不多要重写了……首先你要确定此程序是上网刷题/比赛?还是自学算法知识?如果你有很好的数学功底还可以自学知识,但比赛的话自学是绝对不够的,那需要充分的交流,还有,养成良好的编程风格是一个极其重要的方面,在网上应该可以找到某些大牛的代码集,运气好还有注释版的,可以多多借鉴。下面是一段代码,NetBeans/G++编译通过,你可以尝试改成类结构的。^_^
#include <iostream>
using namespace std;
#define MAXLENGTH 20
// 这是偷懒的部分……不要介意哈
int maxLength[MAXLENGTH + 2][MAXLENGTH + 2];
int preChar[MAXLENGTH + 2][MAXLENGTH + 2];
/*
* 参数说明
* s1:待处理字符串1
* s2:待处理字符串2
* l1:s1长度(不包括字符串结束符'/0')
* l2:s2长度(不包括字符串结束符'/0')
*
* 参数中加const的目的是为了保护外部数据,防止因失误而在函数内部改变了本因无需改变的数值。
*/
int LCSLength(const char* s1, const int l1, const char* s2, const int l2) {
/* 尽量不要在for等语句中定义变量,每个函数一开始最好就把需要的变量全部定义好,同时尽量赋予有意义的函数名 */
/* 当然,有时偷点懒是可以的,但你要确保过了几个月后一看到代码就能很快知道这是啥意思 */
int i, j;
/* maxLength用于存放中间数据,意义:maxLength[i][j]表示:s1前i个字符与s2前j个字符的最长子序列长度
* preChar用于存放当前最长子序列是由那一个自序列得来的
* 因本算法特殊性,需要各额外2位的存储空间
*/
/**/
for (i = 0; i <= l1; i++) maxLength[i][0] = 0;
for (j = 0; j <= l2; j++) maxLength[0][j] = 0;
for (i = 0; i <= l1; i++)
for (j = 0; j <= l2; j++) {
/* 如果s1第i个字符与s2第j个字符相同,则更新maxLength[i+1][j+1]存储的最大值,和preChar存放的前缀自序列位置
* 下同
*/
if (s1[i] == s2[j] && maxLength[i + 1][j + 1] < maxLength[i][j] + 1) {
maxLength[i + 1][j + 1] = maxLength[i][j] + 1;
preChar[i + 1][j + 1] = 1;
}
if (maxLength[i + 1][j] < maxLength[i][j]) {
maxLength[i + 1][j] = maxLength[i][j];
preChar[i + 1][j] = 2;
}
if (maxLength[i][j + 1] < maxLength[i][j]) {
maxLength[i][j + 1] = maxLength[i][j];
preChar[i][j + 1] = 3;
}
}
/* 返回最长子序列长度 */
return maxLength[l1][l2];
}
/**
* s1、s2与上同
* i:s1当前字符序号
* j:s2当前字符序号
*
* i、j初始值为各自字符串长度
*/
void LCSOutput(const char* s1, const int i, const char* s2, const int j) {
if (i >= 0 && j >= 0) {
// 由于是逆向输出,所以先递归,后输出
switch (preChar[i][j]) {
case 1:
LCSOutput(s1, i - 1, s2, j - 1);
break;
case 2:
LCSOutput(s1, i - 1, s2, j);
break;
case 3:
LCSOutput(s1, i, s2, j - 1);
break;
default:
break;
}
if (s1[i] == s2[j])
cout << s1[i];
}
}
int main() {
cout << "最长公共子序列长度:" << LCSLength("1234567890", 10, "1358967", 7) << endl;
cout << "最长公共子序列(不确保唯一):";
LCSOutput("1234567890", 10, "1358967", 7);
cout << endl;
return 0;
}