1 条题解
-
0
算法标签:
字典树 数论
题解
一、题目分析
这段C++代码实现了对输入的多组DNA序列数据的处理功能。程序通过不断读取每组数据中的序列数量
n(m在代码逻辑中未实际使用)和具体的n个DNA序列,先对这些序列进行字典序排序,然后统计每个不同DNA序列的出现次数,进一步再统计这些出现次数各自的频率,最后将频率从1到n依次输出。当输入的n和m都为0时,程序结束运行。二、代码思路
- 数据结构定义:
- 定义宏
maxn为 20005,用于限制存储DNA序列的数组dna以及辅助数组ans和tmp的大小。 - 定义结构体
node,其中包含字符数组str,用于存储单个DNA序列。dna数组被声明为node类型,可存储多个DNA序列。 ans数组用于记录每个出现次数出现的频率,tmp数组用于临时记录每个不同DNA序列的出现次数。
- 定义宏
- 比较函数
cmp:该函数用于为sort函数提供比较规则。接受两个node类型的常量引用a和b,通过strcmp函数比较它们的str成员(即DNA序列)的字典序。当a的字典序小于等于b时返回 1,否则返回 0,从而实现对dna数组中DNA序列按字典序从小到大排序。 - 主函数流程:
- 使用
while(scanf("%d%d",&n,&m))循环读取输入的n和m,当n和m都为 0 时,通过break语句结束循环。 - 利用
for循环根据n的值读取n个DNA序列并存储到dna数组中。 - 调用
sort函数对dna数组进行排序,排序依据为cmp函数。 - 初始化计数器
cnt为 0,用memset函数将ans数组清零,并将tmp[0]初始化为 1。 - 遍历排序后的
dna数组,比较相邻的DNA序列。若相同,则增加tmp[cnt]的值;若不同,则cnt加 1,并将tmp[cnt]初始化为 1。 - 遍历
tmp数组,对于每个出现次数tmp[i],将ans数组中对应下标的元素ans[tmp[i]]加 1,以此统计每个出现次数的频率。 - 最后通过一个
for循环,从 1 到n依次输出ans数组中的元素,即每个出现次数的频率。
- 使用
三、代码实现
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 20005; const int MAX_STR_LEN = 25; struct Node { char str[MAX_STR_LEN]; // 重载小于运算符,用于 std::sort 排序 bool operator<(const Node& other) const { return strcmp(str, other.str) < 0; } }; Node dna[MAXN]; int ans[MAXN], tmp[MAXN]; int main() { int n, m; while (cin >> n >> m) { if (n == 0 && m == 0) { break; } // 输入验证 if (n > MAXN) { cerr << "输入的 n 超出最大限制!" << endl; return 1; } // 读取 DNA 序列 for (int i = 0; i < n; ++i) { cin >> dna[i].str; } // 排序 sort(dna, dna + n); int cnt = 0; memset(ans, 0, sizeof(ans)); tmp[0] = 1; // 统计相同 DNA 序列的数量 for (int i = 0; i < n - 1; ++i) { if (strcmp(dna[i].str, dna[i + 1].str) == 0) { tmp[cnt]++; } else { tmp[++cnt] = 1; } } // 统计每种数量的出现次数 for (int i = 0; i <= cnt; ++i) { ans[tmp[i]]++; } // 输出结果 for (int i = 1; i <= n; ++i) { cout << ans[i] << endl; } } return 0; }四、复杂度分析
- 时间复杂度:
- 排序操作使用
sort函数,其时间复杂度为 ,n为DNA序列的数量。 - 后续的统计操作,包括统计每个不同DNA序列的出现次数以及这些出现次数的频率,均通过遍历数组实现,时间复杂度为 。
- 因此,总体时间复杂度主要由排序操作决定,为 。
- 排序操作使用
- 空间复杂度:
dna数组用于存储n个DNA序列,每个序列最多占用 25 个字符空间,空间复杂度为 。ans和tmp数组的大小均为maxn,也与输入数据规模相关,空间复杂度同样为 。- 所以,整个程序的空间复杂度为 。
五、注意事项
- 输入数据的格式要严格符合代码要求,使用
scanf函数读取n、m和DNA序列时,确保输入的是正确类型的数据,否则可能导致程序运行异常。 - 在处理新的一组输入数据时,
ans数组需要通过memset函数清零,以避免上一组数据的统计结果对当前组产生影响。
- 数据结构定义:
- 1
信息
- ID
- 1946
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者