Find common substring[Dynamic Programming]

今天有人讓我寫個求公共子串的程序,我建議使用動態規劃。如下是我給出的參考的代碼。如有錯誤請斧正。

連續字符

#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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章