说在前面
翻课件的时候发现自己还没学过最小表示法,于是去补了一道板子题=w=
安总赛高!阿岚赛高!
题目
题面
现在给出两个项链的表示,请判断是否是同一条项链
输入输出格式
输入格式:
输入文件共两行,每行一个由0至9组成的字符串,描述一个项链的表示
输出格式:
如果两个项链不同,输出No
不然输出Yes,并在第二行输出项链的最小表示
题解
最小表示法模板题
关于最小表示法的资料不少,me就懒得打了…
推荐这两个(结合着看):
周源《浅析“最小表示法”思想在字符串循环同构问题中的应用》 第23页到第37页
XGHeaven-最小表示法 讲解部分
具体实现可以自行YY
下面是自带大常数的代码
/**************************************************************
Problem: 1398
User: Izumihanako
Language: C++
Result: Accepted
Time:156 ms
Memory:4728 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int lena , lenb ;
char a[2000005] , b[2000005] ;
void GG(){
puts( "No" ) ;
exit( 0 ) ;
}
int getmin( char *ss , int len ){
int i = 0 , j = 1 , k = 0 ;
for( ; i < len && j < len && k < len ; ){
if( ss[i+k] != ss[j+k] ){
if( ss[i+k] > ss[j+k] ){
i = max( j , i + k + 1 ) ;
j = i + 1 ;
} else j = j + k + 1 ;
k = 0 ;
} else k ++ ;
}
return i ;
}
bool check( int pa , int pb ){
for( int k = 0 ; k < lena ; k ++ )
if( a[ pa+k ] != b[ pb+k ] ) return false ;
return true ;
}
void solve(){
int pos_a = getmin( a , lena ) ,
pos_b = getmin( b , lenb ) ;
if( check( pos_a , pos_b ) ){
puts( "Yes" ) ;
for( int k = 0 ; k < lena ; k ++ )
putchar( a[ pos_a+k ] ) ;
} else GG() ;
}
int main(){
scanf( "%s%s" , a , b ) ;
lena = strlen( a ) ;
lenb = strlen( b ) ;
if( lena != lenb )
GG() ;
for( int i = 0 ; i < lena ; i ++ )
a[i+lena] = a[i] , b[i+lenb] = b[i] ;
solve() ;
}