标签
codeforces
字数
944 字
阅读时间
5 分钟
学完Z函数,先用哈希做了一遍,再用Z函数做了一遍,然后搜其他人的题解发现用next数组也能做,就又做了一遍
B. Password
题意
给一串字符串
哈希
前缀和后缀同时哈希,如果匹配上了就根据这个长度遍历一遍
注意要所有的前后缀都判一下,确保是最长的
CPP
const int N = 1e6 + 10;
const int p = 21839; // 以为卡哈希,随便找了个素数,结果是因为最大值
const int MOD = 1e9 + 7;
string s;
int n;
int hf[N]; // hf[i]=p^i
void prepare(int n) {
hf[0] = 1;
for (int i = 1; i <= n; i++) {
hf[i] = (hf[i - 1] * p) % MOD;
}
}
bool check(int sta, int hpre) {
int hinit = hpre;
for (int i = sta + 1; i < n - 1; i++) {
hpre = ((hpre - s[i - sta - 1] * hf[sta]) % MOD + MOD) % MOD;
hpre = (hpre * p % MOD) + s[i];
if (hpre == hinit) {
return true;
}
}
return false;
}
void solveHash() {
cin >> s;
n = s.length();
prepare(n);
int ans = -1;
int hpre = 0, haft = 0;
for (int i = 0; i < n; i++) {
hpre = (hpre * p + s[i]) % MOD;
haft = (haft + (hf[i] * s[n - i - 1]) % MOD) % MOD;
if (hpre == haft) {
if (check(i, hpre)) {
ans = i + 1;
}
}
}
if (ans != -1)
cout << s.substr(0, ans);
else
cout << "Just a legend";
}[[Z函数]]
这个其实只用
从后往前看,如果
接下来就是找有没有比
CPP
const int N = 1e6 + 10;
int z[N];
int e[N];
string s, t;
void zArray(string &s, int n) {
z[0] = n;
for (int i = 1, c = 1, r = 1, len; i < n; i++) {
len = r > i ? min(r - i, z[i - c]) : 0;
while (i + len < n && s[i + len] == s[len]) len++;
if (i + len > r) {
r = i + len;
c = i;
}
z[i] = len;
}
}
void solveZ() {
cin >> s;
t = s;
int n = s.length(), m = n;
zArray(t, m);
int ans = -1;
set<int> match;
// match中存储能与前缀匹配的后缀长度
// 如果在match有比某个z[i]小的值x,说明这个x是答案
for (int i = n - 1; i >= 1; i--) {
if (match.size() > 0) {
auto it = match.upper_bound(z[i]);
// *it是大于z[i]的
// 所以it往前的会小于等于z[i]
if (it != match.begin()) {
it--;
ans = max(*it, ans);
}
}
if (i + z[i] == n) match.insert(z[i]);
}
if (ans != -1) {
cout << s.substr(0, ans);
} else {
cout << "Just a legend";
}
}[[../../../数据结构与算法/字符串/KMP]](用next数组)
先把所有的
如果该
如果该
将
CPP
const int N = 1e6 + 10;
int nxt[N];
string t;
void buildNext(string &t) {
nxt[0] = 0;
int i = 1;
int nlen = 0;
int tlen = t.length();
while (i < tlen) {
if (t[nlen] == t[i]) {
nlen++;
nxt[i] = nlen;
i++;
} else {
if (nlen == 0) {
nxt[i] = 0;
i++;
} else
nlen = nxt[nlen - 1];
}
}
}
bool vis[N];
void solveKMP() {
cin >> t;
buildNext(t);
int n = t.length();
fill_n(vis, n + 5, false);
for (int i = 1; i < n - 1; i++) {
vis[nxt[i]] = 1;
}
int x = nxt[n - 1];
while (!vis[x] && x != 0) {
x = nxt[x - 1];
}
if (x != 0)
cout << t.substr(0, x);
else
cout << "Just a legend";
}