رشته $x$ و $y$ به طول $n$ از اعداد 0 و 1 به شما داده شده است.
اگر $x_k$ برابر باشد با رشته ای که از $k$ بار cyclic shift right خوردن $x$ ساخته می شود، شما باید به دست بیاورید آیا دو عدد $0 \leq i و j \leq n-1$ وجود دارند طوری $x_i \oplus x_j = y$ یا نه ؟
در سطر اول رشته $y$ و در سطر دوم رشته $x$ آمده است. هر رشته از حداکثر $5000$ کاراکتر ساخته شده و اندازه دو رشته برابر است.
با توجه به پاسخ سوال در خروجی رشته Yes یا No را چاپ کنید.
ورودي نمونه | خروجي نمونه |
---|---|
11111 10101 | No |
11110 10101 | Yes |
پاسخ
اگر $x_i \oplus x_j=y$ باشد و هر $2$ طرف را با $x_i$ XOR کنیم داریم $y \oplus x_i=x_j$. یعنی اگر $x_i$ را داشته باشیم مقدار $k$ با شرط اینکه در رابطهی $x_i \oplus k=y$ صدق کند به طور یکتا بهدست میآید. کافیست بین تمام شیفتهای دوری از رشته اصلی مقدار $k$ را جستجو کنیم. اگر $x_j$ برابر با آن بود که $x_jو x_i$ جواب مسئله است و اگر هیچ $x_j$ برابر با $k$ نبود آنگاه $x_i$ نمی تواند در جواب باشد.
پس به ازای تمام $i$ ها از $1$ تا $n$ مقدار $y \oplus x_i$ را بین تمام شیفتهای دوری اعداد جستجو می کنیم و اگر $x_j$ یافت شد که $y \oplus x_i=x_j$ در آنصورت $x_jو x_i$ را به عنوان جواب چاپ کرده و اگر تا آخر هیچ جوابی پیدا نشد، مسئله جواب ندارد.
$y \oplus x_i$ را میتوان از $O(n)$ محاسبه کرد. این مقدار (یک رشته $n$ بیتی) را $k$ مینامیم. برای search آن در بین $n$ رشته (که هر کدام $n$ بیت دارند) اگر بخواهیم از روش بدیهی مقایسه بیت به بیت استفاده کنیم برنامه بیشتر از حد مجاز زمان، طول میکشد. بدین منظور از hash استفاده میکنیم. یعنی به هر رشته $n$ بیتی یک عدد نسبت میدهیم. پس کافیست رشته $n$ بیتی $k$ را hash کنیم $O(n)$ و آن را در بین مقادیر hash اعداد ورودی (که ابتدا یک بار حساب کردیم و ذخیره کردیم) جستجو کنیم $O(n)$. برای اطمینان از صحت جواب به ازای هر بار که hash دو رشته با هم برابر بود $n$ بیت $2$ رشته را کاملا با هم مقایسه کرده تا از برابری انها مطمئن شویم. اگر تابع hash ما خوب باشد تعداد بارهایی که به اشتباه hash دو رشته با هم برابر می شود کم است و اولینباری که به درستی این اتفاق بیفتد برنامه تمام میشود. پس اگر تابع hash ما خوب باشد به ازای یک $i$ خاص تقریبا از $O(n)$هزینه میکنیم. پس در کل زمان برنامه از $O(n^2)$ است.
برای hash یک رشته $n$ بیتی از $0$و$1$ کافیست باقیمانده $\sum_{i=0}^{n-1}a_i\times 2^i$بر $P$ (یک عدد اول بزرگ) محاسبه کنیم. برای این کار در مرحله $i$ ام $2^i \mod P$ را در $a_i$ ضرب کرده و با مقادیر قبلی جمع میکینم و باقیمانده به $P$ حاصل جمع را نگه میداریم.این کار به ازای هر رشته $n$ بیتی از $O(n)$ زمان میبرد و چون کلا $O(n)$رشته را hash میکنیم پس زمان برنامه همان $O(n^2)$میماند.