环状序列 Circular Sequence,ACM/ICPC Seoul 2004,UVa1584(Java语言)

例题3-6 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)

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

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

此处给出英文原题:

  Some DNA sequences exist in circular forms as inthe following figure, which shows a circular sequence“CGAGTCAGCT”, that is, the last symbol “T” in“CGAGTCAGCT” is connected to the first symbol “C”. We alwaysread a circular sequence in the clockwise direction.

   Since it is not easy to store a circular sequence in a computeras it is, we decided to store it as a linear sequence.However, there can be many linear sequences that are obtainedfrom a circular sequence by cutting any place of thecircular sequence. Hence, we also decided to store the linearsequence that is lexicographically smallest among all linearsequences that can be obtained from a circular sequence.

     Your task is to find the lexicographically smallest sequencefrom a given circular sequence. For the example in the figure,the lexicographically smallest sequence is “AGCTCGAGTC”. If there are two or more linear sequences thatare lexicographically smallest, you are to find any one of them (in fact, they are the same).

Input

The input consists of T test cases. The number of test cases T is given on the first line of the inputfile. Each test case takes one line containing a circular sequence that is written as an arbitrary linearsequence. Since the circular sequences are DNA sequences, only four symbols, ‘A’, ‘C’, ‘G’ and ‘T’, areallowed. Each sequence has length at least 2 and at most 100.

Output

Print exactly one line for each test case. The line is to contain the lexicographically smallest sequencefor the test case.

Sample Input

2

CGAGTCAGCT

CTCC

Sample Output

AGCTCGAGTC

CCCT

本题有一个重要的新概念:字典序(lexicographical)。对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小(例如,abc比bcd)小;如果其中一个字符串已经没有更多字符,但另外一个字符串还没结束,则较短的字符串的字典序较小(例如,hi比history小)。

举例,对于序列CTCC,如果需要比较每一种表示法的字典序大小,把字符串看成一个环路,需要使用下标模n的方法进行遍历

 CTCC 
(0)(0+i)%n
(1)  ↑(1+i)%n
(2)     ↑(2+i)%n
(3)       ↑(3+i)%n

其中,n为序列长度,n=4,i<n

Java代码实现如下:

import java.util.Scanner;

public class Main {
	
	public static boolean smaller(String sequence,int p,int q)
	//比较从下标为p处开始的字串的字典序是不是小于从下标为q处开始的字串
	{
		char[] s=sequence.toCharArray();
		int n=sequence.length();//字符串的长度
		for(int i=0;i<n;i++)
		{
			if(s[(p+i)%n]!=s[(q+i)%n])
			{
				//根据字典序的规则,当从该位置开始的字符不同,则比较此两个字符的字典序大小
				return s[(p+i)%n]<s[(q+i)%n];//满足p处开始的序列的字典序小于q处开始的序列的字典序
			}
		}
		return false;//两个字符串字典序相等,将此种情况的值设为false可减少比较次数
		
	}
	
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int count=Integer.parseInt(scanner.nextLine());
		for(int c=0;c<count;c++)
		{
			String sequence=scanner.nextLine();
			int min=0;//假设最小字典序序列是从0开始的序列
			for(int i=1;i<sequence.length();i++)
			//字符串的长度为n,则在每个下标位置开始一次比较
			{
				if(smaller(sequence,i,min))//如果从i开始的序列字典序小于从min下标开始的序列
				{
					min=i;//记录新的min
				}
			}
			//输出获得的最小字典序
			for(int i=0;i<sequence.length();i++)
			{
				System.out.print(sequence.charAt((min+i)%sequence.length()));
			}
			System.out.println();
		}
		scanner.close();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值