今天有人讓我寫個求公共子串的程序,我建議使用動態規劃。如下是我給出的參考的代碼。如有錯誤請斧正。
連續字符
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* Find common substring(Continuous)
* @Author lvxinliang
* @E-Mail [email protected]
*/
void printarr(int **arr, int rows, int cols)
{
int i, j;
for(i = 0; i < rows; i++){
for(j = 0; j < cols; j++){
printf("%5d", arr[i][j]);
}
putchar(10);
}
}
int find_common_substring(const char *str1, const char *str2, char **substr)
{
int cols = strlen(str1);
int rows = strlen(str2);
int i, j;
int max = 0, m_row = 0, m_col = 0;
int **arr = (int **)malloc(sizeof(int *) * rows);
for(i = 0; i < rows; i++)
arr[i] = (int *)malloc(sizeof(int) * cols);
for(i = 0; i < rows; i++){
for(j = 0; j < cols; j++){
if(str2[i] != str1[j]){
arr[i][j] = 0;
}else if(i != 0 && j != 0){
arr[i][j] = arr[i-1][j-1] + 1;
}else{
arr[i][j] = 1;
}
if(max < arr[i][j]){
max = arr[i][j];
m_row = i;
m_col = j;
}
}
}
#ifdef DEBUG
printarr(arr, rows, cols);
printf("max:%d, m_col:%d, m_row:%d\n", max, m_col, m_row);
#endif
*substr = (char *)malloc(max * sizeof(char) + 1);
strncpy(*substr, str1 + m_col - max + 1, max);
for(i = 0; i < rows; i++)
free(arr[i]);
free(arr);
return 1;
}
int main(int argc, const char *argv[])
{
const char str1[] = "abccdeadfe";
const char str2[] = "cbaedeaacdefe";
char *substr = NULL;
printf("str1:%s\n", str1);
printf("str2:%s\n", str2);
find_common_substring(str1, str2, &substr);
printf("The common substring:%s\n", substr);
if(NULL != substr)
free(substr);
substr = NULL;
return 0;
}
非連續字符
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define DEBUG
/**
* Find common substring(Discontinuous)
* @Author lvxinliang
* @E-Mail [email protected]
*/
void printarr(int **arr, int rows, int cols)
{
int i, j;
for(i = 0; i < rows; i++){
for(j = 0; j < cols; j++){
printf("%5d", arr[i][j]);
}
putchar(10);
}
}
int max_int(int x, int y, int z)
{
int max = x;
if(y > max)
max = y;
if(z > max)
max = z;
return max;
}
int find_common_substring(const char *str1, const char *str2, char **substr)
{
int cols = strlen(str1);
int rows = strlen(str2);
int i, j;
int max = 0, max_i = 0, max_j = 0;
int **arr = (int **)malloc(sizeof(int *) * rows);
for(i = 0; i < rows; i++)
arr[i] = (int *)malloc(sizeof(int) * cols);
for(i = 0; i < rows; i++){
for(j = 0; j < cols; j++){
if(i != 0 && j != 0){
if(str1[j] == str2[i])
arr[i][j] = arr[i - 1][j - 1] + 1;
else
arr[i][j] = arr[i - 1][j - 1];
}else{
if(str1[j] == str2[i])
arr[i][j] = 1;
else
arr[i][j] = 0;
}
arr[i][j] = max_int(arr[i][j],i == 0 ? 0 : arr[i - 1][j], j == 0 ? 0 : arr[i][j - 1]);
if(max < arr[i][j]){
max = arr[i][j];
max_j = j;
max_i = i;
}
}
}
#ifdef DEBUG
printarr(arr, rows, cols);
printf("max:%d\n", max);
#endif
*substr = (char *)malloc(max * sizeof(char) + 1);
int tmp = max;
int index = max - 1;
for(i = max_i; i > 0; i--){
for(j = max_j; j > 0; j--){
if(arr[i][j] == tmp){
*(*substr + index) = str1[j];
tmp--;
index--;
max_j--;
break;
}
}
if(tmp == 0)
break;
}
*(*substr + index) = '\0';
for(i = 0; i < rows; i++)
free(arr[i]);
free(arr);
return 1;
}
int main(int argc, const char *argv[])
{
const char str1[] = "abaabcde";
const char str2[] = "bbabcabde";
char *substr = NULL;
printf("str1:%s\n", str1);
printf("str2:%s\n", str2);
find_common_substring(str1, str2, &substr);
printf("The common substring:%s\n", substr);
if(NULL != substr)
free(substr);
substr = NULL;
return 0;
}