算法导论上的 LCS 算法
enum LCS_Flag { LEFT = 1, UP, LEFTUP };
void LCS_print(const char *pStr1, int **LCS_direct, int str1Len, int str2Len);
int LCS(const char *pStr1, const char *pStr2)
{
int rowLen = strlen(pStr1);
int colLen = strlen(pStr2);
int **LCS_Array = (int **)(new int[rowLen + 1]);
for (int i = 0; i <= rowLen; i++)
LCS_Array[i] = (int *)new int[colLen + 1];
int **LCS_direct = (int **)(new int[rowLen + 1]);
for (int i = 0; i <= rowLen; i++)
LCS_direct[i] = (int *)new int[colLen + 1];
for (int i = 0; i <= rowLen; i++)
LCS_Array[i][0] = 0;
for (int j = 0; j <= colLen; j++)
LCS_Array[0][j] = 0;
for (int i = 1; i <= rowLen; i++) {
for (int j = 1; j <= colLen; j++) {
if (pStr1[i - 1] == pStr2[j - 1]) {
LCS_Array[i][j] = LCS_Array[i - 1][j - 1] + 1;
LCS_direct[i][j] = LEFTUP;
}
else if (LCS_Array[i - 1][j] >= LCS_Array[i][j - 1]) {
LCS_Array[i][j] = LCS_Array[i - 1][j];
LCS_direct[i][j] = UP;
}
else {
LCS_Array[i][j] = LCS_Array[i][j - 1];
LCS_direct[i][j] = LEFT;
}
}
}
LCS_print(pStr1, LCS_direct, rowLen, colLen);
return LCS_Array[rowLen][colLen];
}
void LCS_print(const char *pStr1, int **LCS_direct, int str1Len, int str2Len)
{
if (str1Len == 0 || str2Len == 0)
return;
if (LCS_direct[str1Len][str2Len] == LEFTUP) {
LCS_print(pStr1, LCS_direct, str1Len - 1, str2Len - 1);
cout << pStr1[str1Len - 1] << " ";
}
else if (LCS_direct[str1Len][str2Len] == UP) {
LCS_print(pStr1, LCS_direct, str1Len - 1, str2Len);
}
else {
LCS_print(pStr1, LCS_direct, str1Len, str2Len - 1);
}
}
两个字符串的最长公共连续子串,必须是连续的,与LCS不同,LCS不一定要连续的。
int lcstring(const char *s, const char *p)
{
if (s == NULL || p == NULL)
return -1;
int sLen = strlen(s);
int pLen = strlen(p);
int **array = (int **)new int[sLen + 1];
for (int i = 0; i < sLen + 1; ++i)
array[i] = new int[pLen + 1];
for (int i = 0; i < sLen + 1; ++i)
array[i][0] = 0;
for (int j = 0; j < pLen + 1; ++j)
array[0][j] = 0;
int lcnt = 0, pos = 0;
for (int i = 1; i < sLen + 1; ++i) {
for (int j = 1; j < pLen + 1; ++j) {
if (s[i - 1] == p[j - 1]) {
array[i][j] = array[i - 1][j - 1] + 1;
if (lcnt < array[i][j]) {
lcnt = array[i][j];
pos = i - 1;
}
}
else {
array[i][j] = 0;
}
}
}
for (int i = 0; i < lcnt; ++i)
cout << s[i + pos - lcnt + 1];
cout << endl;
for (int i = 0; i < sLen + 1; ++i)
delete[] array[i];
delete[] array;
return lcnt;
}
最长重复子串 (LRS):参考《编程珠玑》的后缀数组实现
#include <iostream>
using namespace std;
int comlen(const char *s, const char *p)
{
int len = 0;
while (*s && *p && *s++ == *p++) {
++len;
}
return len;
}
void LRS_print(const char *s, int maxlen)
{
for (int i = 0; i < maxlen; ++i)
cout << s[i];
cout << endl;
}
// O(n * n)比较
void LRS(const char *s)
{
if (s == NULL)
return;
int slen = strlen(s);
int maxlen = 0;
int spos = 0;
for (int i = 0; i < slen; ++i) {
for (int j = i + 1; j < slen; ++j) {
int templen = comlen(&s[i], &s[j]);
if (templen > maxlen) {
maxlen = templen;
spos = i;
}
}
}
LRS_print(&s[spos], maxlen);
}
int cmpstring(const void *s, const void *p)
{
return strcmp(*(char **)s, *(char **)p);
}
//参考编程珠玑,采用 后缀数组
void LRS_NEW(const char *s)
{
if (NULL == s)
return;
int slen = strlen(s);
const char **array = (const char **)new int[slen]; // 指针要分配 new int
for (int i = 0; i < slen; ++i)
array[i] = &s[i];
qsort(array, slen, sizeof(char *), cmpstring);
int maxlen = 0;
int pos = 0;
for (int i = 0; i < slen - 1; ++i) {
int templen = comlen(array[i], array[i + 1]);
if (maxlen < templen) {
maxlen = templen;
pos = i;
}
}
LRS_print(array[pos], maxlen);
delete[] array;
return;
}
int main(void)
{
char *s = "banana";
LRS(s);
LRS_NEW(s);
return 0;
}