求解两个子串的最长公共子串一般常用的是动态规划算法,但是用后缀数组来处理这一类问题会非常简便,在很多刷题系统中基本都有最长公共子串的处理,所以这一类问题是比较重要的。
c++版本的后缀数组处理最长公共子串问题。
#include <iostream>
#include <string>
using namespace std;
#define MAX 1000
int ranked[MAX]={};
int sa[MAX] ={};
int height[MAX] = {};
int main(){
string iQueryMaxCommString(string& str1, string& str2);
string stringA;
string stringB;
cin >> stringA;
cin >> stringB;
cout << iQueryMaxCommString(stringA,stringB)<< endl;
return 0;
}
void sbubble(string* str,int len){
for (int i = 0;i < len - 1;i++)
for (int j = 0; j < len - i - 1;j++)
if (str[j] > str[j+1]){
string temp = str[j];
str[j] = str[j+1];
str[j+1] = temp;
}
}
int comstr(const string& a,const string& b){
int count = 0;
int len1 = a.length();
int len2 = b.length();
for (int i = 0,j = 0;i < len1&&j < len2;i++,j++)
if (a[i] == b[j])
count++;
else break;
return count;
}
void claheight(string* str,int n){
for (int i = 0,j = 1;i < n-1&&j < n;j++,i++)
height[i] = comstr(str[i],str[j]);
}
string iQueryMaxCommString(string& str1, string& str2){
int lenstr2 = str2.length();
int lenstr1 = str1.length();
string str=str1;
str = str+'$';
str = str + str2;
int len = str.length();
string* backstr = new string[len];
for (int i = 0; i < len;i++)
for (int j = i; j < len;j++)
backstr[i]+=str[j];
sbubble(backstr,len);
for (int i = 0; i < len;i++){
int size = backstr[i].length();
ranked[len - size] = i;
sa[i] = len - size;
}
claheight(backstr,len);
int max = height[0],pos;
for (int i = 0,j = 1;i < len-1&&j < len;i++,j++)
if ((backstr[i].length()>lenstr2+1&&backstr[j].length() <= lenstr2)||
(backstr[j].length()>lenstr2+1&&backstr[i].length() <= lenstr2))
if (max < height[i]){
max = height[i];
pos = i;
}
for (int i = 0; i < len;i++)
if (max == height[i]){
pos = i;
break;
}
string obstr;
for (int i = 0; i < max;i++)
obstr+=backstr[pos][i];
delete[] backstr;
return obstr;
}