以下代码实现了后缀数组算法。
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;
/**--- Reference:http://www.geeksforgeeks.org/suffix-array-set-1-introduction/ ---*/
/**
* @brief store the information of suffix
*/
struct suffix
{
int index;
string suff;
};
/**
* @brief get suffix_array
* @param text
* @param n the length of text
*
* ps:
* b a n a n a
* 5 3 1 0 4 2
*
* 0 banana 5 a
* 1 anana Sort the Suffixes 3 ana
* 2 nana ----------------> 1 anana
* 3 ana alphabetically 0 banana
* 4 na 4 na
* 5 a 2 nana
*
* suffix array for "banana" is {5, 3, 1, 0, 4, 2}
*
* Rank array: the rank array rank[i] represents the rank of the suffix
* beginning at the ith position. That is, if suffix_array[i]=j,
* then rank[j] = i
*
*/
vector<int> buildSuffixArray(string& text, int n)
{
//store suffixes and their indices
struct suffix suffixes[n];
vector<int> sufffix_array;
for (int i = 0; i < n; ++ i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
sort(suffixes, suffixes + n, [](struct suffix a, struct suffix b) {
return strcmp(a.suff.c_str(), b.suff.c_str()) < 0 ? 1 : 0;
});
for (int i = 0; i < n; ++ i)
sufffix_array[i] = suffixes[i].index;
return sufffix_array;
}
vector<int> rankArray(vector<int>& suffix_array)
{
vector<int> rank_array(suffix_array.size());
for (int i = 0; i < suffix_array.size(); i++)
rank_array[suffix_array[i]] = i;
return rank_array;
}
当我将此代码复制到Visual Studio中时,它提醒我表达式必须包含一个常量值,并且不能在此位置使用n
->(struct suffix suffixes[n]
)。以下是我的编译器报告的中文错误消息。
表达式必须含有常量值,参数n不可用作常量值
我不明白为什么,我可以通过gcc正确编译它。
我不知道vector
可能是返回类型值,有人可以给我一些建议吗?
答案 0 :(得分:1)
可变长度数组
我可以通过gcc正确编译它。
在堆栈上创建具有自动存储持续时间的数组suffix suffixes[n]
。
然后通常必须在C ++中的编译时确定此n
。
但是某些C ++编译器支持VLA(可变长度数组),这是C99的新增功能,并允许在堆栈上声明具有非恒定长度的C样式数组。
VC ++不支持C99和VLA,但支持GNU compiler supports VLA as an extension even in C90 and C++。
这就是为什么您可以通过gcc编译以上代码而不会出错的原因。
过去有很多相关的帖子。
如果您在gcc编译命令中添加了-pedantic
(-pedantic-errors
)选项,我们将获得大多数gcc扩展名的警告(错误)。
在这种情况下,使用此选项,我们应该收到以下警告(错误)消息:
ISO C ++禁止使用可变长度数组“后缀”
buildSuffixArray
的实现
我不知道vector如何成为返回类型值
您的buildSuffixArray
甚至在GNU编译器中也会出现分段错误,因为没有分配sufffix_array
。
以下最低限度固定的版本将与GNU编译器一起正常工作:
std::vector<int> buildSuffixArray(const std::string& text, int n)
{
suffix suffixes[n];
for (int i = 0; i < n; ++ i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
std::sort(suffixes, suffixes + n, [](struct suffix a, struct suffix b) {
return std::strcmp(a.suff.c_str(), b.suff.c_str()) < 0 ? 1 : 0;
});
std::vector<int> sufffix_array(n);
for (int i = 0; i < n; ++ i){
sufffix_array[i] = suffixes[i].index;
}
return sufffix_array;
}
但是VC ++不支持VLA,并且上述固定版本仍显示VC ++的编译错误。
以下代码是避免使用VLA(冗余参数n
和lambda表达式)的示例。
这对于gcc和VC ++都可以正常工作。
DEMO is here.
std::vector<int> buildSuffixArray(const std::string& text)
{
std::vector<suffix> suffixes(text.length());
for (std::size_t i = 0; i < suffixes.size(); ++i)
{
suffixes[i].index = i;
suffixes[i].suff = text.c_str() + i;
}
std::sort(suffixes.begin(), suffixes.end(), [](const suffix& a, const suffix& b) {
return (std::strcmp(a.suff.c_str(), b.suff.c_str()) < 0);
});
std::vector<int> sufffix_array(text.length());
for (std::size_t i = 0; i < sufffix_array.size(); ++i){
sufffix_array[i] = suffixes[i].index;
}
return sufffix_array;
}