最长公共子串和最长公共子序列的区别
发布网友
发布时间:2022-04-18 06:11
我来回答
共1个回答
热心网友
时间:2022-04-18 07:40
/* 目标:输出两个字符串的所有公共最长子序列
date: 09-11-26
BY: zggxjxcgx
算法: 判断较短串是否为较长串的子序列,如果是则得到结果;
否则,对较短串进行逐个字符删除操作(将字符替换为'#'表示删除)。
删除操作用递归函数进行实现。每层递归删除一个字符,
若删除一个字符后未得到匹配子序列,则还原该字符所在位置。
第n层递归未找到匹配子序列,则将递归层数加1,重复删除直到剩下空串。
*/
#include<stdio.h>
#include<string.h>
int dep=0; /* 较短串的长度 */
int depflag=0; /*下一步要探测的深度 */
int lastflag=0; /* 是否找到匹配子序列,1为找到 */
int count=0; /* 目标结果的个数 */
int mystrcmp(char *s1,char *s2) /* 判断s2是否为 s1的子串 */
{ while(*s1 *s2)
if(*s2=='#') s2++;
else if(*s2 == *s1) { s1++; s2++; }
else s1++;
while(*s2=='#') s2++;
if(*s2=='\0') return 1;
return 0;
}
void pristr(char *str) /* 打印最长子序列 */
{ if(0==count++) printf("\n公共最长子序列:\n");
printf("%2d:",count);
while(*str)
{ if(*str!='#')
printf("%c",*str);
str++;
}
printf("\n");
}
/*递归函数求最长子序列。start 控制下一个要检测的字符,deptemp控制递归的深度,first为's'表示第一层递归 */
int fun(char *str1,char *str2,char *start,int deptemp,char first)
{ int i=0,j=0;
char *s,cback;
do
{ s=start;
if('s'==first) deptemp=depflag; /* 在第一层设置递归深度 */
while(*s)
{ if(*s=='#') { s++; continue; }
cback=*s; *s='#'; /* 删除当前字符*/
if(mystrcmp(str1,str2)) { pristr(str2); lastflag=1; } /*找到匹配,将lastflag设为1,在完成深度为deptemp+1的探测(找到所有匹配)后退出递归 */
else if(deptemp>0) fun(str1,str2,s+1,deptemp-1,'n'); /* 深度探测,s+1表示从下一个位置开始删除 */
*s=cback; s++; /* 还原该位置的字符,以便下次进行探测 */
}
if('s'==first) ++depflag; /* 删除depflag+1个字符还未找到,则递归深度加1 */
}while(depflag<dep-1 's'==first 0==lastflag); /* 第一层递归具有特殊意义,由三个变量标记是否第一层 */
if(lastflag) return 1; /* lastflag 为1 表示找到匹配子序列 */
return 0;
}
void main()
{ char *s1,*s2;
char st1[]="asfdebjewcwedwk";
char st2[]="sabscdkwss"; // kwfsa
if(strlen(st1)>strlen(st2)) s1=st1,s2=st2; /* 将s1设为较长的串 */
else s1=st2,s2=st1;
printf("\nstr1:%s\nstr2:%s\n",s1,s2);
dep=strlen(s2); /* 得到较短串的长度 */
if(mystrcmp(s1,s2)) pristr(s2);
else if(0==fun(s1,s2,s2,0,'s')) printf("\n没有公共元素!\n");
// printf("%d\n",mystrcmp("afdebjewcwedw","abcdw#"));
}