方法一:利用容器:
将两个字符串中较短的字符串进行分解,分解为不同长度的子串,并保存在set 容器中,这样既可取出相同子串,同时也可以将子串排序,方便查找。利用string类自带的find函数查找重复子串。
#include<iostream>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
int LCS(string sa,string sb)
{
set<string> suff;
string subs,maxstring;
int maxlen=-1;
string s1,s2;//分别用来保存较长和较短字符串
if(sa.size()>sb.size())
{
s1=sa;
s2=sb;
}
else
{
s1=sb;
s2=sa;
}
for(string::size_type i=0;i<s2.size();i++)
for(string::size_type j=2;j<=s2.size()-i;j++)//子串长度
{
subs=s2.substr(i,j);
suff.insert(subs);
}
for(set<string>::iterator it=suff.begin();it!=suff.end();++it)
{
//cout<<*it<<endl;
string st=*it;
if(s1.find(st) !=string::npos)
{
int len=st.size();
if(len>maxlen)
{
maxlen=len;
maxstring=st;
}
}
}
cout<<maxstring<<endl;
return maxlen;
}
int main()
{
string s,sub;
while(getline(cin,s))
{
getline(cin,sub);
cout<<LCS(s,sub)<<endl;
}
}
方法二:利用后缀数组求最长公共子串:
解法:将两个字符串用一个特殊符号(两个字符串中都没有,比如‘#’)连接起来,构造连接后字符串的后缀数组,求后缀数组中的最长公共前缀,要保证最长的公共前缀在原来两个字符串中都出现,而不是只出现在一个字符串中,这就是特殊连接符号的作用。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//qsort比较函数
int pstrcmp(const void *a,const void *b)
{
return strcmp(*(char **)a,*(char **)b);
}
//最长公共子串
int com_suffix(char *p,char *q)
{
int len=0;
int count=0;//用来统计两个子符串中'#'出现的次数,防止两个子串来自同一个字符串
while(*p && *q && *p++==*q++)
{
len++;
if(*q == '#' || *p =='#')
break;
}
while(*q)
{
if(*q++ == '#')
{
count++;
break;
}
}
while(*p)
{
if(*p++ == '#')
{
count++;
break;
}
}
if(count==1)
return len;
return 0;
}
int LCS(char *X,char *Y)
{
char *suff[1000];
int maxlen=-1,maxindex;
int lenx=strlen(X);
int leny=strlen(Y);
int len_suff=lenx+leny+1;
char *arr=new char[len_suff+1];
strcpy(arr,X);
arr[lenx]='#';
strcpy(arr+lenx+1,Y);
for(int i=0;i<len_suff;i++)
suff[i]=&arr[i];
qsort(suff,len_suff,sizeof(char *),pstrcmp);
for(int i=0;i<len_suff-1;i++)
{
int com_len=com_suffix(suff[i],suff[i+1]);
if(com_len>maxlen)
{
maxlen=com_len;
maxindex=i;
}
}
printf("%.*s\n",maxlen,suff[maxindex]);
delete []arr;
return maxlen;
}
int main()
{
printf("%d\n",LCS("aabaaba","aba"));
return 0;
}