寻找若干个字符串的最长公共前缀 Longest Common Prefix

142 篇文章 20 订阅
45 篇文章 0 订阅

问题:给出若干个字符串,找出他们的最长公共前缀子串。问题源于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);
}
    
};

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值