直接暴搜,,。,。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; char s1[210000] , s2[210000] ; int solve(int l1,int r1,int l2,int r2) { int i , mid1 , mid2 ; for(i = 0 ; i <= (r1-l1) ; i++) if( s1[l1+i] != s2[l2+i] ) break ; if( i > (r1-l1) ) return 1 ; if( (r1-l1+1)%2 ) return 0 ; mid1 = (l1+r1)/2 ; mid2 = (r2+l2)/2 ; if( solve(l1,mid1,l2,mid2) && solve(mid1+1,r1,mid2+1,r2) ) return 1 ; if( solve(l1,mid1,mid2+1,r2) && solve(mid1+1,r1,l2,mid2) ) return 1 ; return 0 ; } int main() { int l1 , l2 ; while( scanf("%s %s", s1, s2) != EOF ) { l1 = strlen(s1) ; l2 = strlen(s2) ; if( l1 != l2 || !solve(0,l1-1,0,l2-1) ) printf("NO ") ; else printf("YES ") ; } return 0 ; }
最小表示法,将s1折半深搜,然后推断左側子串和右側字串的关系,假设左側子串大。交换左右字串,使得最后s1是依照规则能够得到最小的串。
s2依照相同的方式转换,然后比較两个串
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define LL __int64 char s1[210000] , s2[210000] ; char c ; void solve(int l,int r,char *s) { if( (r-l+1)%2 ) return ; int i , mid = (l+r)/2 ; solve(l,mid,s) ; solve(mid+1,r,s) ; for(i = 0 ; i < (r-l+1)/2 ; i++) { if( s[l+i] > s[mid+1+i] ) break ; if( s[l+i] < s[mid+1+i] ) return ; } if( i == (r-l+1)/2 ) return ; for(i = 0 ; i < (r-l+1)/2 ; i++) { c = s[l+i] ; s[l+i] = s[mid+1+i] ; s[mid+1+i] = c ; } } int main() { int l1 , l2 ; while( scanf("%s %s", s1, s2) != EOF ) { l1 = strlen(s1) ; l2 = strlen(s2) ; solve(0,l1-1,s1) ; solve(0,l2-1,s2) ; if( l1 != l2 || strcmp(s1,s2) ) printf("NO ") ; else printf("YES ") ; } return 0 ; }