问题:给出若干个字符串,找出他们的最长公共前缀子串。问题源于Leetcode。
假设这里字符串有n个,平均长度为m。
方法:
1、所求的最长公共前缀子串一定是每个字符串的前缀子串。所以随便选择一个字符串作为标准,把它的前缀串,与其他所有字符串进行判断,看是否是它们所有人的前缀子串。这里的时间性能是O(m*n*m)。
2、列出所有的字符串的前缀子串,将它们合并后排序,找出其中个数为n且最长的子串。时间性能为O(n*m+m*n*log(m*n))
3、纵向扫描:从下标0开始,判断每一个字符串的下标0,判断是否全部相同。直到遇到不全部相同的下标。时间性能为O(n*m)。
4、横向扫描:前两个字符串找公共子串,将其结果和第三个字符串找公共子串……直到最后一个串。时间性能为O(n*m)。
5、借助trie字典树。将这些字符串存储到trie树中。那么trie树的第一个分叉口之前的单分支树的就是所求。
代码一(方法1):
class Solution {
public:
string longestCommonPrefix(vector<string> &strs) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(strs.size() == 0)
return "";
if (strs.size() ==1)
return strs[0];
string s = strs[0];
vector<string> spre;
int i;
for(i=1;i<=s.length();i++)
spre.push_back(s.substr(0, i));
string longest = "";
int flag;
for(int j=0; j<spre.size();j++)
{
flag = 1;
for(i=1;i<strs.size();i++)
{
if(!isPrefix(strs[i], spre[j]))
flag = 0;
}
if(flag == 0)
break;
longest = spre[j];
}
return longest;
}
bool isPrefix(string m, string p)
{
int n = 0;
if(m.length() < p.length())
return false;
while(n<p.length())
{
if(m[n] == p[n])
n++;
else
return false;
}
return true;
}
};
代码二(方法3):纵向扫描。
class Solution {
public:
string longestCommonPrefix(vector<string> &strs) {
if(strs.empty())
return "";
int num = strs.size();
int len = strs[0].size();
for(int i=0;i<len;i++)
for(int j=1;j<num;j++)
{
if(i > strs[j].size() || strs[j][i] != strs[0][i])
return strs[0].substr(0, i);
}
return strs[0];
}
};
代码三(方法5):字典树。
class Solution {
public:
typedef struct node {
char ch;
int branch ; //记录分支树,方便最后查询
int times;
node* child[26];
}node, *Trie;
Trie init_Trie()
{
Trie root = (node*)malloc(sizeof(node)); //Trie树的根节点不存储数据
root->branch = 0;
root->times = 0;
for(int i=0;i<26;i++)
root->child[i] = NULL;
return root;
}
void insert_Trie(Trie root, const string str)
{
int n = str.length();
if(n == 0)
{
root->times ++;
return;
}
int i=0;
int idx;
node *p = root;
root->times++;
while(i<n)
{
idx = str[i] - 'a';
if(p->child[idx] != NULL)
{
p = p->child[idx];
p->times ++;
i++;
}
else
{
node* tmp = (node*)malloc(sizeof(node));
tmp->ch = str[i];
tmp->branch = 0;
tmp->times = 1;
for(int j=0;j<26;j++)
tmp->child[j] = NULL;
p->branch ++;
p->child[idx] = tmp;
p = tmp;
i++;
}
}
}
string longestCommonPrefix(vector<string> &strs)
{
int n = strs.size();
if(n == 0)
return "";
int i;
Trie root = init_Trie();
for(i=0;i<n;i++)
insert_Trie(root, strs[i]);
i = 0;
node* p = root;
while(i<strs[0].length() && p->branch == 1 && p->times == n)
{
p = p->child[strs[0][i] - 'a'];
i++;
}
if(p->times < n)
i--;
return strs[0].substr(0,i);
}
};