先说直观的方法,先给出链接:http://blog.csdn.net/xpyimapingchuan/article/details/46822645
直接上代码,很好懂,不多说了。
方案1:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2;
getline(cin,str1);
getline(cin,str2);
char *s;
int num=0;
int max_len=0;
int start,start1,start2;
for(int i=0;i<str1.size();i++)
for(int j=0;j<str2.size();j++)
{
start1=i;
start2=j;
while(str1[start1] && str2[start2] && str1[start1++]==str2[start2++])
{
num++;
if ((start1)==str1.size() || (start2)==str2.size())
break;
}
if(max_len<num)
{
start=i;
max_len=num;
}
num=0;
}
cout<<max_len<<endl;
// system("pause");
}
提交后测试用例未全部通过,只有109分,什么鬼?哪里出问题了 不晓得
方案2:使用动态规划,详细讲解在这里:http://blog.csdn.net/hackbuteer1/article/details/6686931
#include<iostream>
using namespace std;
#define N 1000
int getCommonStrLength(char*,char*);
int main()
{
char pFirstStr[N],pSecondStr[N];
gets(pFirstStr);
gets(pSecondStr);
cout<<getCommonStrLength(pFirstStr,pSecondStr);
//system("pause");
return 0;
}
int getCommonStrLength(char *pf,char *ps)
{
int lenf,lens,indexf,indexs,num=-1;
lenf=strlen(pf);
lens=strlen(ps);
int **cnt=new int*[lenf+1];
for(int i=0;i<lenf+1;++i)
cnt[i]=new int[lens+1];
for(int i=0;i<lenf+1;++i)//第一列初始化为0
cnt[i][0]=0;
for(int i=0;i<lens+1;++i)//第一行初始化为0
cnt[0][i]=0;
for(int i=1;i<lenf+1;++i)
for(int j=1;j<lens+1;++j)
{
if(pf[i-1]==ps[j-1])
cnt[i][j]=cnt[i-1][j-1]+1;
else
cnt[i][j]=0;
if(cnt[i][j]>num)
{
num=cnt[i][j];
indexf=i-1;
indexs=j-1;
}
}
/*int k=num;
char s[100];
s[k--]='\0';
while(indexf>=0&&indexs>=0)
{
if(pf[indexf]==ps[indexs])
{
s[k]=pf[indexf];
--k;
--indexf;
--indexs;
}
else
break;
}
puts(s);*/
for(int i=0;i<lenf+1;++i)
delete [] cnt[i];
delete [] cnt;
return num;
}
提交后还是测试用例未全部通过,113分。又是什么鬼?不知道系统什么打分标准,难道是复杂度之类的?
不死心,于是搜来下面这一份,提交后223分,哇!高了很多,然并卵。还是未全部通过。不知道正确代码肿么写。
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int getLCStringLength(string s1, string s2)
{
if(s1 == "" || s2 == "")
return 0;
int m = s1.size();
int n = s2.size();
vector<vector<int> > table(m+1, vector<int>(n+1));
int biggest = 0; // 记录表中最大值
for(int i=0; i<m+1; ++i)
{
for(int j=0; j<n+1; ++j)
{
// 第一行和第一列置0
if (i == 0 || j == 0)
table[i][j] = 0;
else if(s1[i-1] == s2[j-1])
{
table[i][j] = table[i-1][j-1] + 1;
if(table[i][j] > biggest)
biggest = table[i][j];
}
else // 不相等置0
table[i][j] = 0;
}
}
return biggest;
}
int main ()
{
string input, s1, s2;
getline(cin, input);
stringstream ss(input);
ss >> s1;
ss >> s2;
cout << getLCStringLength(s1, s2) << endl;
return 0;
}
既然是用的别人的,给出链接:http://blog.csdn.net/lisonglisonglisong/article/details/45218665
这是别人刷的2011年的OJ,但估计也木有全部通过吧。
主要是通过这道题初步了解了动态规划解决最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)问题
动态规划求解最大公共字符串问题见方案2
下面对最大公共子序列详细说明以备忘:
1、序列str1和序列str2
·长度分别为m+1和n+1;
·创建1个二维数组L[m+1,n+1];
·初始化L数组0行0列内容为0
·m和n分别从0开始,m++,n++循环:
- 如果str1[m] == str2[n],则L[m,n] = L[m - 1, n -1] + 1;
- 如果str1[m] != str2[n],则L[m,n] = max{L[m,n - 1],L[m - 1, n]}
·最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
·从数组L中找出一个最长的公共子序列
2、从数组L中查找一个最长的公共子序列
i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)
·长度分别为m+1和n+1;
·创建1个二维数组L[m+1,n+1];
·初始化L数组0行0列内容为0
·m和n分别从0开始,m++,n++循环:
- 如果str1[m] == str2[n],则L[m,n] = L[m - 1, n -1] + 1;
- 如果str1[m] != str2[n],则L[m,n] = max{L[m,n - 1],L[m - 1, n]}
·最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
·从数组L中找出一个最长的公共子序列
2、从数组L中查找一个最长的公共子序列
i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)
直接在方案2基础上稍作改动即可:
#include<iostream>
using namespace std;
#define N 1000
int getCommonStrLength(char*,char*);
int main()
{
char pFirstStr[N],pSecondStr[N];
gets(pFirstStr);
gets(pSecondStr);
cout<<getCommonStrLength(pFirstStr,pSecondStr);
system("pause");
return 0;
}
int getCommonStrLength(char *pf,char *ps)
{
int lenf,lens,indexf,indexs,max_len=-1;
lenf=strlen(pf);
lens=strlen(ps);
int **cnt=new int*[lenf+1];
for(int i=0;i<lenf+1;++i)
cnt[i]=new int[lens+1];
for(int i=0;i<lenf+1;++i)//第一列初始化为0
cnt[i][0]=0;
for(int i=0;i<lens+1;++i)//第一行初始化为0
cnt[0][i]=0;
for(int i=1;i<lenf+1;++i)
for(int j=1;j<lens+1;++j)
{
if(pf[i-1]==ps[j-1])
cnt[i][j]=cnt[i-1][j-1]+1;
else
{
if(cnt[i][j-1]>cnt[i-1][j])
cnt[i][j]=cnt[i][j-1];
else
cnt[i][j]=cnt[i-1][j];
}
if(cnt[i][j]>max_len)
{
max_len=cnt[i][j];
indexf=i;
indexs=j;
}
}
int k=max_len;
char s[1000];
s[k--]='\0';
while(indexf>=0&&indexs>=0)
{
if(pf[indexf-1]==ps[indexs-1])
{
s[k]=pf[indexf-1];
--k;
--indexf;
--indexs;
}
else
{
if(cnt[indexf][indexs-1]>cnt[indexf-1][indexs])
--indexs;
else
--indexf;
}
}
puts(s);
for(int i=0;i<lenf+1;++i)
delete [] cnt[i];
delete [] cnt;
return max_len;
}