寻找一个字符串中连续出现次数最多的子串

来源:互联网 发布:java 文字转图片 编辑:程序博客网 时间:2024/05/20 15:12

一、生成后缀数组搜索

算法描述

首先获得后缀数组,然后
1.第一行第一个字符a,与第二行第一个字符b比较,不等,则
2.第一行前两个字符ab,与第三行前两个字符cb比较,不等,则
3.第一行前三个字符abc,与第四行前三个字符bcb比较,不等,则
4.第一行前四个......
上述过程就相当于在原始字符串中,
第一趟,a与b比较,ab与cb比较,abc与bcb比较,abcb与cbca比较,abcbc与bcabc比较,abcbcb与cabc比较......
第二趟,b与c比较,bc与bc比较(相等,则继续向后取长度为2的子串比较,碰到不等为止,本例中因碰到ab停止),bcb与cbc比较......
第三趟,c与b比较,cb与cb比较(相等),cbc与bca比较......
......

使用后缀数组方便编程实现



//vs2005#include "stdafx.h"#include <iostream>#include <vector>#include <utility>#include <string>using namespace std;pair<int,string> fun(const string &str){vector<string> substrs;int maxcount=1,count=1;string substr;int i,len=str.length();for(i=0;i<len;++i){substrs.push_back(str.substr(i,len-i));cout<<substrs[i]<<endl;}for(i=0;i<len;++i){for(int j=i+1;j<len;++j){count=1;if(substrs[i].substr(0,j-i)==substrs[j].substr(0,j-i)){++count;for(int k=j+(j-i);k<len;k+=j-i){if(substrs[i].substr(0,j-i)==substrs[k].substr(0,j-i))++count;elsebreak;}if(count>maxcount){maxcount=count;substr=substrs[i].substr(0,j-i);}}}}return make_pair(maxcount,substr);}int _tmain(int argc, _TCHAR* argv[]){string str;pair<int,string> rs;str="abcbcbcabc";rs=fun(str);cout<<rs.second<<':'<<rs.first<<endl;return 0;}

二、优化空间复杂度

把字符串用后缀树的形式表现出来如下:

a b c a b c a b c d e .substr[0]

b c a b c a b c d e ....substr[1]

c a b c a b c d e .......substr[2]

a b c a b c d e ..........substr[3]

b c a b c d e .............substr[4]

c a b c d e ...............substr[5]

a b c d e .................substr[6]

b c d e ...................substr[7]

c d e .....................substr[8]

d e ........................substr[9]

e ..........................substr[10]

可以观察到,若存在连续出现的字串,则满足 substr[0].substr(i,j-i) == substr[j].substr(0,j-i),例如上例中的

substr[0].substr(0,3-0) == substr[3].substr(0,3-0)

我们换一种方式来看,不需要生成后缀组,但思想还是一样的。

代码:

代码中str.substr(pos2,offset)其实相当于后缀组的substr[pos2].substr(0,offset)

把字符串写成后缀组其实相当于站在不同的位置往后看这个数组,所以其实并不需要额外增加存储空间来生成后缀组。

#include <iostream>#include <string>using namespace std;void main(){    string str = "abcabcabcccccdefefefefefef";    int len = str.length();    int maxCount = 0;    string longest = "";    for(int pos1 = 0; pos1 < len; pos1++)        for(int pos2 = pos1 + 1; pos2 < len; pos2++){            if(str.substr(pos1,pos2-pos1) == str.substr(pos2,pos2-pos1)){                int offset = pos2-pos1;                int count = 2;                for(int k = pos2 + offset; k <= len; k += offset){                    if(str.substr(pos1,offset) == str.substr(k,offset)){                        count += 1;                    }else{                        break;                    }                }                if(count > maxCount){                    maxCount = count;                    longest = str.substr(pos1,offset);                }            }        }    cout << longest << "," << maxCount << endl;}


0 0
原创粉丝点击