voidexkmp() { for (int i = 1; i < str.size(); i++) { if (i <= r && z[i - l] < r - i + 1) z[i] = z[i - l]; else { z[i] = max(0, r - i + 1); while (i + z[i] < str.size() && str[i + z[i]] == str[z[i]]) ++z[i]; } if (z[i] > r) { l = i; r = i + z[i] - 1; } } }
intmain() { cin >> str; exkmp(); for (int i = 1; i < str.size(); i++) { if (i + z[i] == str.size()) maxn = max(maxn, z[i] - 1); elseif (i + z[i] < str.size()) maxn = max(maxn, z[i]); } for (int i = 1; i < str.size(); i++) if (i + z[i] == str.size() && z[i] <= maxn) minn = max(minn, z[i]); if (minn) for (int i = 0; i < minn; i++) printf("%c", str[i]); else printf("Just a legend"); return0; }
Solution 2
本题也有 KMP 做法。计算出 S 正序和倒序时的前缀函数 nxta 和 nxtb。因此只要 S 正序和倒序时在同一位置有相同长度的相同前后缀,即为满足答案。
int z[N], l, r, nxta[N], nxtb[N], ans; string str, s;
voidkmp() { for (int i = 1; i < str.size(); i++) { int j = nxta[i - 1]; while (j > 0 && str[i] != str[j]) j = nxta[j - 1]; if (str[j] == str[i]) ++j; nxta[i] = j; } s = str; for (int i = 0; i < str.size(); i++) s[i] = str[str.size() - i - 1]; for (int i = 1; i < s.size(); i++) { int j = nxtb[i - 1]; while (j > 0 && s[i] != s[j]) j = nxtb[j - 1]; if (s[j] == s[i]) ++j; nxtb[i] = j; } }
intmain() { cin >> str; kmp(); for (int i = 1; i < str.size(); i++) { if (nxta[i] == nxtb[str.size() - i - 2 + nxta[i]]) ans = max(ans, nxta[i]); } if (ans) for (int i = 0; i < ans; i++) printf("%c", str[i]); else printf("Just a legend"); return0; }