華為OJ2011-最長公共子串
阿新 • • 發佈:2019-02-19
一、題目描述
描述:
計算兩個字串的最大公共子串(Longest Common Substring)的長度,字元區分大小寫。
輸入:
輸入兩個字串
輸出:
輸出一個整數
樣例輸入:
asdfas werasdfaswer
樣例輸出:
6
二、解題報告
與最長公共子序列(參見《動態規劃DP》)一樣,最長公共子串也可以使用動態規劃解決,只不過思路不太一樣。準確地說,是打表的方式不一樣。
舉個例子:s1 = bab
,s2 = caba
。表如下
具體打表的方法是:
- 第一行、第一列初始化為 0;
- 對於其他的格子:
- 若對應的兩個字元相等,格子的值設為左上角的值加 1。
- 若對應的兩個字元不相等,直接置 0 。
這樣的話,表中的最大元素就是 最長公共子串 的長度。並且也可以很容易看出最長公共子串有 2 個,分別是ba
和ab
。
C++程式碼如下:
#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;
}
三、擴充套件
如何輸出所有的最長公共子串?
很簡單,我們記錄下 s1 和 s2 的公共子串分別在 s1 、s2 中起始位置(即表中值為 1 的座標)。打表完成以後,我們已經知道了最長公共子串的長度length
,通過substr()
判斷即可:
s1.substr(i-1, length) == s2.substr(j-1, length)
C++程式碼如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printLCString(string s1, string s2)
{
if(s1 == "" || s2 == "")
return;
int m = s1.size();
int n = s2.size();
vector<vector<int> > table(m+1, vector<int>(n+1));
int biggest = 0; // 記錄表中最大值
vector<pair<int, int> > firstPos; // 記錄子串開始的座標
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];
if(table[i][j] == 1)
firstPos.push_back(make_pair(i, j));
}
else // 不相等置0
table[i][j] = 0;
}
}
// 輸出所有的最長公共子串
vector<pair<int, int> >::iterator beg = firstPos.begin();
for( ; beg!=firstPos.end(); ++beg)
{
int start1 = beg->first-1;
int start2 = beg->second-1;
if(s1.substr(start1, biggest) == s2.substr(start2, biggest))
cout << s1.substr(start1, biggest) << endl;
}
}
int main ()
{
string s1 = "hello,world,james";
string s2 = "james is saying hello";
printLCString(s1, s2);
return 0;
}