HackerRank Sequential Prefix Function(可持久化kmp)
HackerRank Sequential Prefix Function(可持久化kmp)
题目大意
维护 nxt 数组,要求支持动态加字符,删末尾
解题思路
可持久化 kmp 模板题
首先我们有个结论,将一个串的 border 数组排序,可以分成 \(\Theta(\log n)\) 个等差数列,这意味着循环串周期串的出现,如果 \(2 \times nxt \le i\) 那么直接跳即可,否则就会出现重复的部分,我们根据 border 的性质或者手玩一下发现它出现了周期,因此我们直接跳等差数列即可,我有另一种办法,考虑每次跳的时候都是判定下一个字符相等,我们直接记个 pre 表示一段 nxt 的下一个字符不相等的地方即可,看代码吧
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;
template <typename T>
void read(T &x) {
x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
for (;isdigit(c);c=getchar()) x=x*10+(c^48);
if (f) x=-x;
}
template<typename F>
inline void write(F x, char ed = '\n')
{
static short st[30];short tp=0;
if(x<0) putchar('-'),x=-x;
do st[++tp]=x%10,x/=10; while(x);
while(tp) putchar('0'|st[tp--]);
putchar(ed);
}
template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }
template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }
const int N = 205200;
int nxt[N], pre[N], st[N], tp, n;
int main() {
read(n);
for (int i = 1, x;i <= n; i++) {
char op[5]; scanf ("%s", op);
if (op[0] == '+') {
read(x); int j = tp;
while (j && st[nxt[j] + 1] != x) j = pre[j];
st[++tp] = x, j = nxt[j] + 1;
if (tp == 1) nxt[1] = pre[1] = 0;
else if (st[j] == x) {
nxt[tp] = j;
if (st[nxt[j] + 1] == st[j + 1]) pre[tp] = pre[j];
else pre[tp] = j;
}
else nxt[tp] = pre[tp] = 0;
}
else tp--;
write(nxt[tp]);
}
return 0;
}
/*
8
+ 1
+ 2
+ 2
+ 1
+ 2
+ 2
+ 1
+ 1
12212211
*/