题目概述:
长度为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 ;
}