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

*/
posted @ 2020-08-02 15:22  Hs-black  阅读(612)  评论(2编辑  收藏  举报