环状序列(算法竞赛入门经典二)

简介: 环状序列(算法竞赛入门经典二)

环状序列

长度为n的环状串有n种表示法,分别为某个位置开始顺时针得到。例如,图中的环状串有10种表示:
CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称为“最小表示”。

输入一个长度为n(n<=100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示。例如,CTCC的最小表示是CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC.

输入:
在输入文件的第一行 为序列数量。每一个测试用例都需要一行包含一个循环序列,
这个序列被写成一个任意的线性序列。
由于循环序列是DNA串,只有四个符号:A,C,G,T。
每一序列的长度为n(2<=n<=100)。

输出:
每行为串的字典序最小的序列。下面的样例为2个串的序列。

样例输入:
2
CGAGTCAGCT
CTCC

样例输出:
AGCTCGAGTC
CCCT

include<stdio.h>

include<string.h>

define maxn 100

int less(const char* s, int p, int q)//见下注释2
{

int n = strlen(s);

for (int i = 0; i < n; i++)
{
    if (s[(p + i) % n] != s[(q + i) % n])//%n是为了将转了一圈后将那一圈减去,类似13:00就是1:00
        return s[(p + i) % n] < s[(q + i) % n];/*这里p是main里i, q是ans,一旦找到某个字符串i打

头比ans打头字典序更小,返回1,才会把i赋值给ans(见main())。注意是字典序最小,不是打头
元素最小,所以要用for循环,一个一个往下找,找到不一样的才return*/

}
return 0; //相等

}

int main()
{

int C;
scanf("%d", &C);//输入要判断几个环状序列

while (C--)//见下注释1
{
    char s[maxn];//创立数组存储字符串
    scanf("%s", s);//输入要判断的序列
    int n = strlen(s);//计算该序列的长度
    int ans = 0;  // ans是指最小的那个开头的数,默认最小序列就是s[0]开头

    // 让默认序列与其他序列比较 
    for (int i = 1; i < n; i++)//见注释2
        if (less(s, i, ans))
         ans = i;

    // 输出最小序列
    for (int j = 0; j < n; j++)
    {
        putchar(s[(ans + j) % n]);
    }
    putchar('\n');
}
return 0;

}

注释1
这里我曾经想了好久,不理解为什么会用循环,其实后来发现是我理解错了,这里我原来以为输入的是字符串长度,其实是用来判断多个环状序列的

注释2
这里就是整个判断的关键部分,由less这个函数可以直接判断出最小序列

首先我们从一个数进入,例如就是c

然后此时i=1,ans=0,接着进入less函数(注意此时i就是p,ans就是q)。进入第一次循环,此时就判断s[1]是否等于s[0]

这里很明显c<g,那么s[1]就大于s[0],所以判断不成立返回0,接着返回主函数,ans值不变,接着i变为2,再进入函数,此时就是比较s[2]和s[0]

这时s[2]<s[0],判断成立返回1,则ans值改变,变为2,那么下一次序列就从s[2]开头,接着i变为3,就是比较s[3]和s[2]

很明显不成立,则ans值不改变,紧着向下进行

好接下来遇到第二个问题,如果开头相同怎么办?

此时ans=2,i=6,进入函数,结果s[2]==s[6],那么这时候for循环就发挥作用啦,比较第二个数,也就是s[3]和s[7]

结果发现还相等,就再for一次,比较s[4]和s[8]

这里就可以看出s[8]<s[4]啦,判断成立,返回1,ans的值改变为i,也就是6,那么此时就是从s[6]开头啦

那么到这其实思路就很清晰啦,%n就是为了让它的数不超过字符串长度(这里就是9),每次判断都是寻找最小的数,如果相同,就再比较下一级,直到找出小的序列,然后改变开头数(ans)。

main函数里的for就是用来判断开头数哪个小,而less函数里的for就是用来判断如果开头数相同,那么就比较下一个数,再比较下一个,直到不相同(ps:如果开头数不同的话其实for循环是没啥用的)

相关文章
|
20天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
2月前
|
机器学习/深度学习 人工智能 算法
AI入门必读:Java实现常见AI算法及实际应用,有两下子!
本文全面介绍了人工智能(AI)的基础知识、操作教程、算法实现及其在实际项目中的应用。首先,从AI的概念出发,解释了AI如何使机器具备学习、思考、决策和交流的能力,并列举了日常生活中的常见应用场景,如手机助手、推荐系统、自动驾驶等。接着,详细介绍了AI在提高效率、增强用户体验、促进技术创新和解决复杂问题等方面的显著作用,同时展望了AI的未来发展趋势,包括自我学习能力的提升、人机协作的增强、伦理法规的完善以及行业垂直化应用的拓展等...
164 3
AI入门必读:Java实现常见AI算法及实际应用,有两下子!
|
3月前
|
机器学习/深度学习 数据采集 人工智能
机器学习算法入门与实践
【7月更文挑战第22天】机器学习算法入门与实践是一个既充满挑战又极具吸引力的过程。通过掌握基础知识、理解常见算法、注重数据预处理和模型选择、持续学习新技术和参与实践项目,你可以逐步提高自己的机器学习技能,并在实际应用中取得优异的成绩。记住,机器学习是一个不断迭代和改进的过程,保持好奇心和耐心,你将在这个领域走得更远。
|
3月前
|
消息中间件 存储 算法
实战算法的基础入门(2)
实战算法的基础入门
|
3月前
|
算法 大数据
实战算法的基础入门(1)
实战算法的基础入门
|
3月前
|
算法 Java
实战算法的基础入门(3)
实战算法的基础入门
|
2月前
|
存储 算法
【C算法】编程初学者入门训练140道(1~20)
【C算法】编程初学者入门训练140道(1~20)
|
4月前
|
算法 程序员
高阶算法班从入门到精通之路
高阶算法班从入门到精通之路
31 3
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
机器学习算法入门:从K-means到神经网络
【6月更文挑战第26天】机器学习入门:从K-means到神经网络。文章涵盖了K-means聚类、逻辑回归、决策树和神经网络的基础原理及应用场景。K-means用于数据分组,逻辑回归适用于二分类,决策树通过特征划分做决策,神经网络则在复杂任务如图像和语言处理中大显身手。是初学者的算法导览。
|
4月前
|
自然语言处理 算法
ransformers从入门到精通:常用的subword tokenizer算法
- WordPiece、BPE/BBPE最小字词进行合并最终字词,BPE/BBPE直接采用词频判断合并规则而WordPiece采用最大似然的方式 - unigram采用从最大的字词集合里移除那些对语料库整体概率贡献最小的子词【6月更文挑战第7天】
93 3