算法竞赛入门经典(第二版) | 程序3-10 生成元 (UVa1584,Circular Sequence)

题目概述:

长度为n的环状串有n种表示法, 字典序最小的称为最小表示。输入一个长度为n(n<100)的环状字符串的一种表示方法,输出最小表示 。
如:CTCC 为环状字符串的一种表示方法,它的所有表示方法分别为:CTCC、TCCC、CCCT、CCTC。其中最小表示为CCCT。

储备知识:
字典序:

字典序:按字典顺序从两个字符串的第一位开始比较,字典顺序靠前的串较小。若两串前n个字母都相同,但串A长于串B,则串B小。
如:ABCD小于BCDA

思路:

将序列放入无头指针循环链表(一定是无头指针的链表,否则判每次遍历都需跳过头指针,非常麻烦)。
利用循环链表的循环特性求出每种情况, 分别比较。 代码其实并不长,只是写链表占了很多行。

收获:

掌握了无头指针循环链表的定义方法,学到了字典序的概念。

代码:
#include <iostream>
#include <cstdio>
#include <list> 
#include <cstdlib>
#include <cstring>

using namespace std ;

typedef struct LNode *lbook ;
struct LNode{
	char x ;
	struct LNode *list ;
}; 

//创建 
lbook Creat(char a[] , int len1) {
	lbook P , P1 , P2 ;
	P = (lbook)malloc(sizeof(LNode)) ;      //无头指针 
	P->x = a[0] ;							//无头指针的链表定义方式 
	
	P1 = P;
	int j = 1 ;
	while(j != len1) {
		char s = a[j++] ;
		lbook P3 ;
		P3 = (lbook)malloc(sizeof(LNode)) ;
		P3->x = s ;
		
		P3->list = P1->list ;
		P1->list = P3 ;
		P1 = P3 ;
	}
	P1->list = P ;							//循环链表 
	return P ;
}

//查找 
lbook Find(lbook P , int len , int i) { 		 
	int k = 0 ; 
	while(k++ != len) {
		if(k == i) return P ;
		P = P->list ;
	}
} 

int main()
{
	//悔棋很麻烦。 
	lbook L ;
	char a[105] ;
	
	cin >> a ; 				//输入 
	int len = strlen(a) ;	//输入字符串a的长度
	L = Creat(a , len) ;  
 
	if(len == 1) {  		//特殊情况:长度为1则直接输出。 
		Show(L,len) ;
		return 0 ;
	}
	
	//每条链比较字典序,n条链需比较n-1次。
	int k = 0 ; 
	int s = 2 ;
	char c[105] ; 				//存放结果
	strcpy(c,a) ; 				//c先行存放a数组的值。 
	while(k++ != (len-1)) {
		lbook LL = Find(L, len, s) ;
		s++ ;
		
		//定义d数组,分别存放环状序列所有结果 
		char d[105] ; 
		int r = 0 ;
		while(r != len) {
			d[r] = LL->x ;
			r++ ;
			LL = LL->list ;
		}
		//若c>d,则将d赋给c,重复操作。 
		if((strcmp(c,d)) == 1)  strcpy(c,d) ;
	} 
	cout << c ; 
	return 0 ;
 } 
发布了27 篇原创文章 · 获赞 16 · 访问量 1952

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104283697