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

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

原创  2013年10月20日 11:44:19

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

[cpp]  view plain  copy
  1. class Solution {  
  2. public:  
  3.     string longestCommonPrefix(vector<string> &strs) {  
  4.         // Note: The Solution object is instantiated only once and is reused by each test case.  
  5.         if(strs.size() == 0)  
  6.             return "";  
  7.         if (strs.size() ==1)  
  8.             return strs[0];  
  9.         string s = strs[0];  
  10.         vector<string> spre;  
  11.         int i;  
  12.         for(i=1;i<=s.length();i++)  
  13.             spre.push_back(s.substr(0, i));  
  14.         string longest = "";  
  15.         int flag;  
  16.         for(int j=0; j<spre.size();j++)  
  17.         {  
  18.             flag = 1;  
  19.             for(i=1;i<strs.size();i++)  
  20.             {  
  21.                 if(!isPrefix(strs[i], spre[j]))  
  22.                     flag = 0;  
  23.             }  
  24.             if(flag == 0)  
  25.                 break;  
  26.             longest = spre[j];  
  27.         }  
  28.         return longest;  
  29.     }  
  30.   
  31.     bool isPrefix(string m, string p)  
  32.     {  
  33.         int n = 0;  
  34.         if(m.length() < p.length())  
  35.             return false;  
  36.         while(n<p.length())  
  37.         {  
  38.             if(m[n] == p[n])  
  39.                 n++;  
  40.             else  
  41.                 return false;  
  42.         }  
  43.         return true;  
  44.     }  
  45. };  

代码二(方法3):纵向扫描。

[cpp]  view plain  copy
  1. class Solution {  
  2. public:  
  3.     string longestCommonPrefix(vector<string> &strs) {  
  4.         if(strs.empty())  
  5.             return "";  
  6.         int num = strs.size();  
  7.         int len = strs[0].size();  
  8.         for(int i=0;i<len;i++)  
  9.             for(int j=1;j<num;j++)  
  10.             {  
  11.                 if(i > strs[j].size() || strs[j][i] != strs[0][i])  
  12.                     return strs[0].substr(0, i);  
  13.             }  
  14.         return strs[0];  
  15.     }  
  16. };  
代码三(方法5):字典树。

[cpp]  view plain  copy
  1. class Solution {  
  2. public:  
  3. typedef struct node {   
  4.     char ch;  
  5.     int branch ; //记录分支树,方便最后查询  
  6.     int times;  
  7.     node* child[26];  
  8. }node, *Trie;  
  9.   
  10. Trie init_Trie()  
  11. {  
  12.     Trie root = (node*)malloc(sizeof(node)); //Trie树的根节点不存储数据  
  13.     root->branch = 0;  
  14.     root->times = 0;  
  15.     for(int i=0;i<26;i++)  
  16.         root->child[i] = NULL;  
  17.     return root;  
  18. }  
  19.   
  20. void insert_Trie(Trie root, const string str)  
  21. {  
  22.     int n = str.length();  
  23.     if(n == 0)  
  24.     {  
  25.         root->times ++;  
  26.         return;  
  27.     }  
  28.     int i=0;  
  29.     int idx;  
  30.     node *p = root;  
  31.     root->times++;  
  32.     while(i<n)  
  33.     {  
  34.         idx = str[i] - 'a';  
  35.         if(p->child[idx] != NULL)  
  36.         {  
  37.             p = p->child[idx];  
  38.             p->times ++;  
  39.             i++;  
  40.         }  
  41.         else  
  42.         {  
  43.             node* tmp = (node*)malloc(sizeof(node));  
  44.             tmp->ch = str[i];  
  45.             tmp->branch = 0;  
  46.             tmp->times = 1;  
  47.             for(int j=0;j<26;j++)  
  48.                 tmp->child[j] = NULL;  
  49.   
  50.             p->branch ++;  
  51.             p->child[idx] = tmp;  
  52.             p = tmp;  
  53.             i++;  
  54.         }  
  55.     }  
  56. }  
  57.   
  58. string longestCommonPrefix(vector<string> &strs)  
  59. {  
  60.     int n = strs.size();  
  61.     if(n == 0)  
  62.         return "";  
  63.   
  64.     int i;  
  65.     Trie root = init_Trie();  
  66.     for(i=0;i<n;i++)  
  67.         insert_Trie(root, strs[i]);  
  68.   
  69.     i = 0;  
  70.     node* p = root;  
  71.     while(i<strs[0].length() && p->branch == 1 && p->times == n)  
  72.     {  
  73.         p = p->child[strs[0][i] - 'a'];  
  74.         i++;  
  75.     }  
  76.     if(p->times < n)  
  77.         i--;  
  78.     return strs[0].substr(0,i);  
  79. }  
  80.       
  81. };  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值