Описание] [Название
даст вам две длину \ (п \) строка спрашивает , может ли префикс строки строки в спину так , что две строки равны. Если да, то вам может потребоваться выход лексикографически наименьший строка символов , полученный с помощью описанной выше операции может быть.
[Формат ввода
два целых числа первого ряда \ (п, Т \) .
Следующие две строки длины \ (п \) строки.
[Формат вывода]
Если да, то выход \ (TAK \) , в противном случае выход \ (NIE \) . Если \ (. 1 = Т \) , выходная линия строки вам нужно лексикографически наименьший следующий.
Диапазон данных []
\ (\ п ле 1 млн \)
Во- первых, что \ (TAK \) ?
Собственный Baidu перевод
Подумайте о практике насилия получит обратно префикс строки , так что исходная строка соответствует одному циклическому сдвигу, так что вы можете перечислить все циклический сдвиг.
Сложность времени \ (O (N ^ 2) \)
在这里介绍一种\(O(n)\)求出一个字符串最小的循环移位的方法
先将原串复制一遍加在原串后面 即 将\(ABCD\) 变为 \(ABCDABCD\) 这样在这个新字符串中任意取一段长为\(n\)的子串一定是原串的一种循环移位。
维护两个指针\(i, j\)和当前子串长度\(len\),表示现在正在比较从\(i\)开始的长度为\(len+1\)的子串和从\(j\)开始的长为\(len+1\)的子串。
若某一时刻,\(s[i+len] \neq s[j+len]\)
若\(s[i+len] < s[j+len]\),则说明从\(i\)开始的子串比从\(j\)开始的子串小,所以最小子串一定不会从\(j\)开始。此时可以直接让\(j = j + len + 1\),然后继续匹配。
反之让\(i = i + len + 1\)。
为什么这样可以保证正确性呢?
反证:如果此时 \(s[i+len] < s[j+len]\) ,即\(j\)被“淘汰”了,假设最小子串其实是从\(s[j+k](1 \le k \le len)\)开始的,那么一定存在从\(s[i+k]\)开始的子串会比它小。
举例:"\(ABAABBC\)": 此时\(i\)在\(s[1]\),\(j\)在\(s[4]\),\(len=2\)时发现\(s[1+2] < s[4+2]\),所以\(j\)可以直接跳到7。因为从\(S[5], S[6]\)开始的子串一定不会成为最小的。对于从\(s[5]\)开始的"\(BBC\)..."有从\(s[2]\)开始的"\(BA\)..."比它小,从\(s[6]\)开始的\(s[3]\)一定比它小。
【代码实现】
#include <bits/stdc++.h>
#define ri register int
using namespace std;
inline int read() {
int ret = 0, flag = 1;
char ch = getchar();
while (ch > '9' || ch < '0') {
if (ch == '-') flag = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ret = (ret << 1) + (ret << 3) + (ch ^ '0');
ch = getchar();
}
return ret * flag;
}
int n, t;
int i, j;
int min1, min2;
char s1[2000005], s2[2000005];
bool yes = 1;
int main() {
n = read(); t = read();
scanf("%s", s1+1);
scanf("%s", s2+1);
for (ri a = 1; a <= n; a++) {
s1[a + n] = s1[a];
s2[a + n] = s2[a];
}
i = 1; j = 2;
while (i <= n && j <= n) {
if (i == j) j++;
for (int len = 0; ; len++) {
if (s1[i+len] < s1[j+len]) {
j = j + len + 1;
break;
}
if (s1[j+len] < s1[i+len]) {
i = i + len + 1;
break;
}
}
}
if (i <= n) min1 = i;
else min1 = j;
i = 1; j = 2;
while (i <= n && j <= n) {
if (i == j) j++;
for (int len = 0; ; len++) {
if (s2[i+len] < s2[j+len]) {
j = j + len + 1;
break;
}
if (s2[j+len] < s2[i+len]) {
i = i + len + 1;
break;
}
}
}
if (i <= n) min2 = i;
else min2 = j;
for (ri len = 0; len < n; len++) {
if (s1[min1 + len] != s2[min2 + len]) {
yes = 0;
break;
}
}
if (yes) {
puts("TAK");
if (t) {
for (ri a = min1; a <= min1 + n - 1; a++) {
putchar(s1[a]);
}
puts("");
}
} else puts("NIE");
return 0;
}