后缀数组dc3模板(范围1e6而且多样例要用dc3)

字符串排序与高度计算
本文介绍了一种基于三字符周期性的字符串排序算法及其高度计算方法,并实现了一个高效的RMQ查询来辅助高度计算,适用于字符串处理与算法竞赛。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include <iostream>
#include <string>
#include <set>
#include <map>
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
using namespace std;
const int MAXN = 500000+10;
const int N = MAXN;
const int INF=1e9+7;
int wa[MAXN],wb[MAXN],wv[MAXN],Ws[MAXN];
int sa[MAXN],height[MAXN],RANK[MAXN];
int len[MAXN];
int c0(int *r,int a,int b)
{
    return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
}
int c12(int k,int *r,int a,int b)
{
    if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
    else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
}
void sort(int *r,int *a,int *b,int n,int m)
{
    int i;
    for(i=0;i<n;i++) wv[i]=r[a[i]];
    for(i=0;i<m;i++) Ws[i]=0;
    for(i=0;i<n;i++) Ws[wv[i]]++;
    for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
    for(i=n-1;i>=0;i--) b[--Ws[wv[i]]]=a[i];
    return;
}
void dc3(int *r,int *sa,int n,int m) //涵义与DA 相同
{
    int i,j,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
    int *rn=r+n;
    r[n]=r[n+1]=0;
    for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
    sort(r+2,wa,wb,tbc,m);
    sort(r+1,wb,wa,tbc,m);
    sort(r,wa,wb,tbc,m);
    for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
        rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
    if(p<tbc) dc3(rn,san,tbc,p);
    else for(i=0;i<tbc;i++) san[rn[i]]=i;
    for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
    if(n%3==1) wb[ta++]=n-1;
    sort(r,wb,wa,ta,m);
    for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
    for(i=0,j=0,p=0;i<ta && j<tbc;p++)
        sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
    for(;i<ta;p++) sa[p]=wa[i++];
    for(;j<tbc;p++) sa[p]=wb[j++];
    return;
}
void calheight(int *r,int *sa,int n)
{   // 此处N为实际长度
    int i,j,k=0;
    // height[]的合法范围为 1-N, 其中0是结尾加入的字符
    for(i=1;i<=n;i++)
        RANK[sa[i]]=i;
    // 根据SA求RANK
    for(i=0;i<n; height[RANK[i++]] = k )
        // 定义:h[i] = height[ RANK[i] ]
        for(k?k--:0,j=sa[RANK[i]-1];
            r[i+k]==r[j+k]; k++);
    //根据 h[i] >= h[i-1]-1 来优化计算height过程
}

int dp[MAXN][20];
void Rmq_Init(int n){
    int m=floor(log(n+0.0)/log(2.0));
    for(int i=1;i<=n;i++) dp[i][0]=height[i];
    for(int i=1;i<=m;i++){
        for(int j=n;j;j--){
            dp[j][i]=dp[j][i-1];
            if(j+(1<<(i-1))<=n)
                dp[j][i]=min(dp[j][i],dp[j+(1<<(i-1))][i-1]);
        }
    }
}
int Rmq_Query(int l,int r){
    int a=RANK[l],b=RANK[r];
    if(a>b) swap(a,b);
    a++;
    int m=floor(log(b-a+1.0)/log(2.0));
    return min(dp[a][m],dp[b-(1<<m)+1][m]);
}

<think>我们面对的任务是:给每个十六进制数字串添加"0x"前缀,并在每个数字串后添加逗号。 注意:用户输入的是十六进制值(hexadecimal values),所以我们需要处理的是字符串形式的十六进制数字。 步骤: 1. 理解需求:输入可能是一串或多串十六进制数字(可能以空格、换行或其他分隔符分隔),需要为每个数字串添加"0x"前缀,并在其后添加逗号。 2. 处理方式:我们可以将输入字符串分割成单独的十六进制数字串,然后对每个数字串进行添加前缀和逗号的操作,最后将它们合并。 注意:由于用户没有提供具体的输入字符串,我们假设输入是一串用空格分隔的十六进制数字(如:"1A 2B 3C")。但实际中,分隔符可能是空格、换行或其他。因此,我们需要考虑如何分割字符串。 然而,根据问题描述,用户意图是“在数字串前添加0x前缀,并在每个数字串后添加逗号”,所以我们可以这样设计: - 首先,将输入字符串按空白字符(包括空格、制表符、换行等)分割成多个子字符串。 - 然后,过滤掉分割后可能出现的空字符串(如果有的话)。 - 对每个非空子字符串,添加"0x"前缀和逗号后缀。 - 最后,将处理后的所有字符串连接起来(可以用逗号分隔,但注意每个元素后面已经加了逗号,所以直接连接即可,但这样最后一个元素后面也会多一个逗号,通常我们可能需要去掉最后一个逗号,或者每个元素单独处理后再用逗号连接?) 但是,用户要求是“在每个数字串后添加逗号”,所以每个元素后面都有一个逗号。那么整个结果就是:0x1A,0x2B,0x3C, 注意最后一个元素后面也有逗号。如果用户不希望最后一个元素后面有逗号,那么我们需要在最后去掉多余的逗号。但根据问题描述,用户要求是“append comma”,所以每个后面都加,那么我们就每个后面都加,最后可能多一个逗号。但用户可能希望生成一个列表形式,如用于数组初始化。 然而,根据常见编程实践,在初始化数组时,每个元素后面有逗号,包括最后一个元素后面也可以有逗号(在有些语言中允许,如Python、JavaScript等),但有些语言可能不建议。所以,我们需要明确用户的使用场景。 但是,用户没有说明具体用途,所以我们可以按照以下两种方式之一处理: a) 每个元素后面都加逗号,包括最后一个元素。这样生成的字符串最后会有一个逗号。 b) 在元素之间加逗号,最后一个元素不加。这样生成的字符串符合大多数编程语言中数组的写法(除了最后一个元素后面没有逗号)。 然而,用户明确要求“在每个数字串后添加逗号”,所以我们应该采用a)方式,即每个后面都加逗号。 但是,如果用户提供的输入字符串中已经包含了逗号,怎么办?如输入可能是"1A,2B,3C"。这时我们需要先去除原有的逗号,然后再分割?或者,我们假设输入是纯的十六进制数字串,用空白符分隔。 因此,我们设计一个通用的方法: 步骤: 1. 使用正则表达式或字符串分割函数,按非十六进制字符(即非0-9, A-F, a-f的字符)进行分割?但这样可能过于复杂。 2. 更简单的方法:按空白字符分割(因为用户输入可能是空格或换行分隔),然后过滤掉空字符串。 但是,如果输入是连续的一串数字(如"1A2B3C"),那么我们需要按固定长度分割吗?问题没有说明,所以我们不能假设固定长度。因此,我们只能按空白字符分割。 因此,我们假设输入是用空白字符(空格、制表符、换行等)分隔的多个十六进制数字串。 处理流程: 输入字符串 -> 分割(split)成列表(按空白字符) -> 过滤掉空字符串 -> 对每个元素添加"0x"前缀和逗号后缀 -> 合并成一个字符串 但是,如果用户输入的是连续字符串,比如"1A2B3C",那么分割后整个字符串会作为一个元素,这样我们就会得到"0x1A2B3C,",这显然不是我们想要的(因为用户希望每个数字串都单独处理,而这里1A、2B、3C应该是三个数字串)。所以,我们需要明确数字串的长度吗? 问题:用户没有说明每个十六进制数字串的长度。十六进制数字串可以是任意长度(比如1个字节、2个字节等)。所以,我们不能按固定长度分割。 因此,我们只能要求输入是已经分隔好的(即每个十六进制数字串之间用分隔符分开)。所以,我们按照空白字符分割是合理的。 如果用户输入的是没有分隔符的连续字符串,那么我们需要用户指定每个数字串的长度(如每两个字符作为一个数字串)。但问题没有提供这个信息,所以我们不能做这个假设。 因此,我们只处理用空白字符分隔的情况。 代码实现(以Python为): 假设输入字符串为:s = "1A 2B 3C" 步骤: 1. 分割:parts = s.split() # 默认按任意空白字符分割 2. 过滤空字符串:parts = [part for part in parts if part != &#39;&#39;] 3. 对每个部分添加前缀和后缀:parts_processed = [&#39;0x&#39; + part + &#39;,&#39; for part in parts] 4. 合并:result = &#39;&#39;.join(parts_processed)结果:&#39;0x1A,0x2B,0x3C,&#39; 注意:最后一个元素后面也有逗号。 如果用户希望最后一个元素后面没有逗号,我们可以修改为: result = &#39;,&#39;.join([&#39;0x&#39;+part for part in parts]) 这样得到:&#39;0x1A,0x2B,0x3C&#39; 但是,用户要求是“在每个数字串后添加逗号”,所以每个后面都要有逗号,那么第一种方式符合要求。不过,第一种方式得到的是每个元素都带逗号,然后连接起来,所以最后一个元素后面也有逗号。 但是,用户问题中并没有说是否允许最后一个元素后面有逗号。所以,我们可以按照用户要求严格实现:每个数字串后面都加逗号,不管是不是最后一个。 因此,我们采用第一种方式。 但是,如果用户输入为空,那么我们应该返回空字符串。 另外,我们也可以考虑其他编程语言的实现,但用户没有指定语言,所以我们以Python为,并说明思路。 如果用户需要其他语言的实现,我们可以提供类似逻辑。 总结:使用字符串分割,然后逐个添加前缀和后缀,再合并。 代码示(Python): ```python def add_prefix_and_suffix(hex_str): # 按空白字符分割 parts = hex_str.split() # 过滤空字符串 parts = [part for part in parts if part.strip() != &#39;&#39;] # 为每个部分添加&#39;0x&#39;前缀和逗号后缀 processed_parts = [&#39;0x&#39; + part + &#39;,&#39; for part in parts] # 合并 result = &#39;&#39;.join(processed_parts) return result # 示用法 input_str = "1A 2B 3C" output_str = add_prefix_and_suffix(input_str) print(output_str) # 输出:0x1A,0x2B,0x3C, ``` 注意:如果输入字符串中包含非空白字符的分隔符(比如逗号、分号等),那么上述方法不会分割这些字符。如输入"1A,2B,3C",分割后得到[&#39;1A,2B,3C&#39;],这样整个作为一个元素。所以,我们需要先处理掉非十六进制字符?或者允许用户指定分隔符。 但是,用户没有指定分隔符,所以我们只能按空白字符分割。如果用户输入包含其他分隔符,那么需要先预处理(比如替换为空格)或者使用更复杂的分割方式。 我们可以改进:使用正则表达式按非十六进制数字的字符分割?但这样也不完全,因为十六进制数字串中可能包含字母,所以我们不能按非数字分割。所以,我们只能按空白字符分割。 因此,我们建议用户输入时使用空白字符分隔。如果用户输入包含其他分隔符,那么需要先进行替换。 另一种方法:提取所有连续的十六进制数字串(由0-9, A-F, a-f组成的连续字符串)。这样,无论输入中有什么分隔符,我们都可以提取出十六进制数字串。 步骤: 使用正则表达式:re.findall(r&#39;[0-9A-Fa-f]+&#39;, hex_str) 来提取所有连续的十六进制字符串。 这样,即使输入是"1A,2B;3C"或"1A 2B,3C",我们也能正确提取出[&#39;1A&#39;,&#39;2B&#39;,&#39;3C&#39;]。 改进后的代码: ```python import re def add_prefix_and_suffix(hex_str): # 使用正则表达式提取所有连续的十六进制数字串 hex_values = re.findall(r&#39;[0-9A-Fa-f]+&#39;, hex_str) # 为每个十六进制串添加前缀和后缀 processed_parts = [&#39;0x&#39; + value + &#39;,&#39; for value in hex_values] result = &#39;&#39;.join(processed_parts) return result # 示用法 input_str = "1A,2B;3C 4D" # 混合分隔符 output_str = add_prefix_and_suffix(input_str) print(output_str) # 输出:0x1A,0x2B,0x3C,0x4D, ``` 这种方法更健壮,可以处理各种分隔符。 注意:如果输入中有连续的非十六进制字符,比如"1A,,2B",那么中间的逗号会被跳过,提取出[&#39;1A&#39;,&#39;2B&#39;]。 另外,如果输入中包含非十六进制字符但也是字母的,比如"GH",则不会被提取,因为正则表达式只匹配十六进制字符(0-9, A-F, a-f)。 因此,我们采用正则表达式的方法。 如果用户需要其他语言的实现,我们可以提供思路,但这里以Python为。 如果用户没有Python环境,可能需要用其他语言,但问题没有指定,所以我们先提供Python版本。 此外,如果用户需要处理大字符串,这种方法也是有效的。 最后,我们输出结果字符串。 注意:如果输入为空字符串,则正则表达式会返回空列表,然后结果也是空字符串。 所以,这个函数可以处理各种情况。 因此,我们推荐使用正则表达式的方法。 总结步骤: 1. 使用正则表达式提取所有连续的十六进制数字串(由0-9, A-F, a-f组成的连续字符串)。 2. 对每个提取到的数字串,添加"0x"前缀和逗号后缀3. 将所有处理后的字符串连接成一个字符串。 代码如上。 如果用户需要在其他编程语言中实现,逻辑类似,如在JavaScript中: ```javascript function addPrefixAndSuffix(hexStr) { // 使用正则表达式匹配所有十六进制数字串(连续的数字和A-Fa-f字母) let regex = /[0-9A-Fa-f]+/g; let matches = hexStr.match(regex) || []; // 如果没有匹配则为空数组 // 为每个匹配添加前缀和后缀 let processedParts = matches.map(match => &#39;0x&#39; + match + &#39;,&#39;); // 合并 return processedParts.join(&#39;&#39;); } // 示 let inputStr = "1A,2B;3C 4D"; let outputStr = addPrefixAndSuffix(inputStr); console.log(outputStr); // 输出: "0x1A,0x2B,0x3C,0x4D," ``` 注意:在JavaScript中,`String.prototype.match`方法会返回所有匹配的数组,如果没有匹配则返回null,所以我们用`|| []`来保证是数组。 其他语言如Java、C++等也可以类似实现,使用相应的正则表达式库。 因此,我们提供了两种常见语言的实现。 由于用户没有指定语言,我们以Python和JavaScript为,并说明思路,用户可以根据需要自行转换。 如果用户需要处理的是文件或大量数据,可以使用相应的流式处理,但这里我们处理的是字符串。 最后,我们按照要求生成相关问题。 注意:相关问题必须基于用户的原始问题和回答内容。 相关问题可能包括: 1. 如何去掉最后一个多余的逗号? 2. 如果十六进制数字串中包含小写字母,如何统一转换为大写? 3. 如何将处理后的结果保存到文件中? 4. 如果输入字符串中包含非十六进制字符(如G、H等),如何处理这些字符? 5. 如果每个十六进制数字串的长度是固定的(比如两个字符),如何按固定长度分割? 我们选择三个: §§相关问题§§: 1. 如何去除最后一个多余的逗号? 2. 如何将十六进制字符串中的字母转换为大写? 3. 如果输入字符串没有分隔符,如何按固定长度分割十六进制数字串?</think>### 添加 0x 前缀和逗号的方法 #### 方法一:Python 字符串处理 ```python import re def format_hex(input_str): # 提取所有十六进制数字串(忽略大小写) hex_values = re.findall(r&#39;[0-9A-Fa-f]+&#39;, input_str) # 添加 0x 前缀和逗号 formatted = [f"0x{val.upper()}," for val in hex_values] return &#39;&#39;.join(formatted) # 示用法 input_str = "1A 2B 3C DEADBEEF" output = format_hex(input_str) print(output) # 输出: 0x1A,0x2B,0x3C,0xDEADBEEF, ``` #### 方法二:JavaScript 正则处理 ```javascript function formatHex(inputStr) { // 匹配十六进制数字串(不区分大小写) const hexValues = inputStr.match(/[0-9A-F]+/gi) || []; // 添加前缀和逗号 return hexValues.map(val => `0x${val.toUpperCase()},`).join(&#39;&#39;); } // 示用法 const inputStr = "1A 2B 3C DEADBEEF"; const output = formatHex(inputStr); console.log(output); // 输出: 0x1A,0x2B,0x3C,0xDEADBEEF, ``` #### 方法三:命令行处理 (sed + awk) ```bash # 步骤: # 1. 用空格替换所有非十六进制字符 # 2. 添加 0x 前缀和逗号 echo "1A, 2B; 3C DEADBEEF" | sed &#39;s/[^0-9A-Fa-f]\+/ /g&#39; | awk &#39;{ for(i=1;i<=NF;i++) printf "0x%s,", toupper($i) }&#39; # 输出: 0x1A,0x2B,0x3C,0xDEADBEEF, ``` ### 关键说明 1. **十六进制匹配规则**: - 正则表达式 `[0-9A-Fa-f]+` 匹配连续十六进制字符 - 忽略大小写(`DEADBEEF` 和 `deadbeef` 均有效) 2. **特殊字符处理**: - 自动过滤逗号、分号等非十六进制字符 - 保留原始数字串顺序(如输入 `"3C 1A 2B"` 输出 `0x3C,0x1A,0x2B,`) 3. **输出规范**: - 每个数字串前添加 `0x` 前缀 - 每个数字串后添加逗号 - 字母统一转换为大写(符合十六进制规范) 4. **边缘情况**: - 空输入返回空字符串 - 无有效十六进制串时返回空 - 连续空格/分隔符自动跳过
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值