我尝试在C ++中为以下问题生成/获得有效的实现:
我必须blob(const char * data,size_t length),我称之为“blob1”和“blob2”。现在我想在“blob1”中获得“blob2”的最长前缀。如果最长的前缀在“blob1”中多次,我想得到索引最大的前缀。
这里有一个例子(这里的blob只是ASCII字符串,所以更容易阅读这个例子):
blob1 = HELLO LOOO HELOO LOOO LOO JU
blob2 = LOOO TUS
以下是blob2的所有有效前缀:
{L
,LO
,LOO
,LOOO
,LOOO
,LOOO T
,LOOO TU
,{{1} }}
LOOO TUS
中blob2
的最长前缀为blob1
。它有两次:
LOOO
所以我想获得第二个的索引,即HELLO *LOOO *HELOO *LOOO *LOO JU
,以及前缀的长度6
。
不幸的是blob1和blob2改变很多次,因此创建树或其他复杂结构可能会很慢。
你知道一个很好的算法来解决这个问题吗?
谢谢。
干杯 凯文
答案 0 :(得分:1)
我不知道这是否是解决此问题的最佳算法(我确定,这不是),但是,我想这是一个很好的算法。这个想法很简单,首先从blob1中的blob2中搜索最低标记。找到匹配项后,尝试查看是否可以在此位置匹配biggers标记。如果是这样,请更新令牌长度。
从最后一站开始继续搜索,但此时,搜索来自blob2的更新令牌长度的令牌。找到匹配项后,尝试查看是否可以在此位置匹配biggers标记。如果是这样,请更新令牌长度。重复上一步骤直到缓冲区结束。
贝娄是一个简单的通量图,试图解释这个算法,并按顺序,一个简单的完整程序,显示一个实现。
#include <algorithm>
#include <vector>
#include <iostream>
/////////////////////0123456789012345678901234567
const char str1[] = "HELLO LOOO HELOO LOOO LOO JU";
const char str2[] = "LOOO TUS";
int main()
{
std::vector<char> blob1(strlen(str1));
std::vector<char> blob2(strlen(str2));
blob1.reserve(30);
blob2.reserve(30);
std::copy(str1, str1+strlen(str1), blob1.begin());
std::copy(str2, str2+strlen(str2), blob2.begin());
auto next = blob1.begin();
auto tokenLength = 1;
auto position = -1;
while ( std::next(next, tokenLength) < blob1.end() ) {
auto current = std::search(next,
blob1.end(),
blob2.begin(),
std::next(blob2.begin(), tokenLength));
if (current == blob1.end() )
break;
position = std::distance(blob1.begin(), current);
next = std::next(current, 1);
for (auto i = tokenLength; std::next(blob2.begin(), i) < blob2.end(); ++i) {
auto x = std::search(std::next(current, i),
std::next(current, i + 1),
std::next(blob2.begin(), i),
std::next(blob2.begin(), i + 1));
if ( x != std::next(current, i) )
break;
++tokenLength;
}
}
std::cout << "Index: " << position << ", length: " << tokenLength << std::endl;
}