最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

sa函数的表达式

IT圈 admin 38浏览 0评论

2024年4月11日发(作者:羊尔柳)

sa函数的表达式

sa函数是一种字符串算法,全称为“Suffix Array”,即后缀数组。它

是一种对字符串进行快速排序的数据结构,用于解决字符串相关问题,

如最长公共子串、模式匹配等。

sa函数的表达式如下:

sa(string s, int n, int m) {

for (int i = 1; i <= n; i++) {

rk[i] = s[i];

cnt[rk[i]]++;

}

for (int i = 2; i <= m; i++) {

cnt[i] += cnt[i - 1];

}

for (int i = n; i >= 1; i--) {

sa[cnt[rk[i]]--] = i;

}

for (int k = 1; k <= n; k <<= 1) {

int num = 0;

for (int i = n - k + 1; i <= n; i++) {

tmp[++num] = i;

}

for (int i = 1; i <= n; i++) {

if (sa[i] > k) {

tmp[++num] = sa[i] - k;

}

}

for (int i = 0; i <= m; i++) {

cnt[i] = 0;

}

for (int i = 1; i <= n; i++) {

cnt[rk[tmp[i]]]++;

}

for (int i = 2; i <= m; ++i) {

cnt[i] += cnt[i - 1];

}

for (int j = n; j >= 1 ; j--) {

sa[cnt[rk[tmp[j]]]--] = tmp[j];

}

swap(rk, tmp);

rk[sa[1]] = 1;

num = 1;

for (int i = 2; i <= n; i++) {

if (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + k] ==

tmp[sa[i - 1] + k]) {

rk[sa[i]] = num;

} else {

rk[sa[i]] = ++num;

}

}

if (num == n) {

break;

}

m = num;

}

}

其中,s为输入的字符串,n为字符串的长度,m为字符集大小。rk

数组表示字符串中每个字符的排名,cnt数组表示每个字符出现的次数,

sa数组表示后缀数组,tmp数组用于排序时的临时存储。

该函数的主要思路是利用桶排实现对字符串的排序。首先将每个字符

看作一个单独的后缀,并按照其字典序进行排序。然后将相邻两个后

缀合并成一个新的后缀,并再次进行排序。重复以上步骤直到所有后

缀都被合并成一个。

在实现过程中,需要注意以下几点:

1. 排序时需要考虑到相同前缀的情况,因此需要使用倍增法实现。

2. 在合并相邻两个后缀时,需要保证新生成的后缀仍然是按照字典序

排列。

3. 在计算rk数组时,需要考虑到相同后缀的情况。

4. 在每次排序后需要更新rk数组和sa数组。

5. 在最后一次排序时,如果所有后缀都已经合并成一个,则可以直接

退出循环。

总之,sa函数是一种高效的字符串算法,在解决字符串相关问题时具

有重要的应用价值。对于程序员来说,了解sa函数的表达式及其实现

原理是非常有益的。

2024年4月11日发(作者:羊尔柳)

sa函数的表达式

sa函数是一种字符串算法,全称为“Suffix Array”,即后缀数组。它

是一种对字符串进行快速排序的数据结构,用于解决字符串相关问题,

如最长公共子串、模式匹配等。

sa函数的表达式如下:

sa(string s, int n, int m) {

for (int i = 1; i <= n; i++) {

rk[i] = s[i];

cnt[rk[i]]++;

}

for (int i = 2; i <= m; i++) {

cnt[i] += cnt[i - 1];

}

for (int i = n; i >= 1; i--) {

sa[cnt[rk[i]]--] = i;

}

for (int k = 1; k <= n; k <<= 1) {

int num = 0;

for (int i = n - k + 1; i <= n; i++) {

tmp[++num] = i;

}

for (int i = 1; i <= n; i++) {

if (sa[i] > k) {

tmp[++num] = sa[i] - k;

}

}

for (int i = 0; i <= m; i++) {

cnt[i] = 0;

}

for (int i = 1; i <= n; i++) {

cnt[rk[tmp[i]]]++;

}

for (int i = 2; i <= m; ++i) {

cnt[i] += cnt[i - 1];

}

for (int j = n; j >= 1 ; j--) {

sa[cnt[rk[tmp[j]]]--] = tmp[j];

}

swap(rk, tmp);

rk[sa[1]] = 1;

num = 1;

for (int i = 2; i <= n; i++) {

if (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + k] ==

tmp[sa[i - 1] + k]) {

rk[sa[i]] = num;

} else {

rk[sa[i]] = ++num;

}

}

if (num == n) {

break;

}

m = num;

}

}

其中,s为输入的字符串,n为字符串的长度,m为字符集大小。rk

数组表示字符串中每个字符的排名,cnt数组表示每个字符出现的次数,

sa数组表示后缀数组,tmp数组用于排序时的临时存储。

该函数的主要思路是利用桶排实现对字符串的排序。首先将每个字符

看作一个单独的后缀,并按照其字典序进行排序。然后将相邻两个后

缀合并成一个新的后缀,并再次进行排序。重复以上步骤直到所有后

缀都被合并成一个。

在实现过程中,需要注意以下几点:

1. 排序时需要考虑到相同前缀的情况,因此需要使用倍增法实现。

2. 在合并相邻两个后缀时,需要保证新生成的后缀仍然是按照字典序

排列。

3. 在计算rk数组时,需要考虑到相同后缀的情况。

4. 在每次排序后需要更新rk数组和sa数组。

5. 在最后一次排序时,如果所有后缀都已经合并成一个,则可以直接

退出循环。

总之,sa函数是一种高效的字符串算法,在解决字符串相关问题时具

有重要的应用价值。对于程序员来说,了解sa函数的表达式及其实现

原理是非常有益的。

发布评论

评论列表 (0)

  1. 暂无评论