bzoj3940 [Usaco2015 Feb]Censoring
自从会了sam,似乎已经不知道acam该怎么写了ovo 这个题就是强行用ac自动机记录匹配到某个位置的时候的状态.然后如果走到一个终态的话就可以强行删掉一段,然后把当前状态变为上一个状态. 最初没有想到有可能会连续删除,于是挂了很久.最后用官网上的数据还是过不了第9个点,然后交bzoj居然过了.好神奇.我猜想是迅雷挂了hhh毕竟usaco的数据用wget根本搞不下来好伤心. 所以我还是太弱ovo
自从会了sam,似乎已经不知道acam该怎么写了ovo 这个题就是强行用ac自动机记录匹配到某个位置的时候的状态.然后如果走到一个终态的话就可以强行删掉一段,然后把当前状态变为上一个状态. 最初没有想到有可能会连续删除,于是挂了很久.最后用官网上的数据还是过不了第9个点,然后交bzoj居然过了.好神奇.我猜想是迅雷挂了hhh毕竟usaco的数据用wget根本搞不下来好伤心. 所以我还是太弱ovo
后缀数组的基础题ovo好久没写sa了还自己yy了半天ovo 为啥感觉每次写sa写得都不一样ovo 求出height数组之后,如果一个位置的height大于上一个位置的,那么高出来的这一截都是新的一个答案.那么直接朴素地去找它出现了多少次就好了.我相信出题人没有办法构造数据把我卡到三方. 所以各种题都要再复习一下ovo
考试的时候do big die去刷bzoj.大概下午会hug zero. sam的第二题.其实这个玩意是应该用sa做的,不过现在我觉得sa没有sam简单.虽然sam的构造和性质还是一团大雾. 这个题可以做出原串的后缀树,然后在上面dp一下.每个点对答案的贡献为任意两个不在同一子树的终态对数*深度. 然后倒过来建sam,它的parent树就是原串的后缀树.虽然我还没有成功理解这个东西. 然后坑了一会的一件事情是新建的nq节点的right集合为空.因为它只是一个扩展点,但是不是一个接受态ovo 我还是太弱啊怎么办.
我的SAM第一题。按照惯例几乎是照着std抄的OVO。本来以为是要在SAM上DP,后来发现好像是并列的,于是比较开心。 SAM这个东西主要就是用来匹配子串用的。建法详见clj的课件,然后现在我还处于消化状态中。 SAM匹配多个串的话也比较好弄,直接在串末再加一个字符集里没有的元素就好了。 现在假设已经用SAM匹配出了第i个位置往左ml[i]个位置都是可以匹配的,那么可以二分一个答案,然后用单调队列来DP判断。写法比较简单,虽然我急着去写SAM所以这部分也是蒙过去的。 然后网上的2个std就有2种不同的答案还和我不一样。最后还是wd学长的代码靠谱orz。 现在我可以说我是写过SAM的人了哈哈。
<div class="post_brief"><p> 久了不写manacher又手生了只好抄红书了。</p> 后面的过程就是对每个位置i找一个最远的位置j满足j在i为中心的回文子串的一半以内且j最小。然后直接拿个set就能搞定。 #include <cstdio> #include <cstring> #include <algorithm> #include <set> using namespace std; const int maxn = 500009; char a[maxn]; int d[maxn << 1], n; void manacher() { d[0] = 1; for (int i = 1, j = 0; i < (n << 1) - 1; ++ i) { int p(i >> 1), q(i - p), r(((j + 1) >> 1) + d[j] - 1); if (r < q) d[i] = 0; else d[i] = min(r - q + 1, d[(j << 1) - i]); while (p - d[i] >= 0 && q + d[i] < n && a[p - d[i]] == a[q + d[i]]) ++ d[i]; if (q + d[i] - 1 > r) j = i; } }...
以前觉得不会,仔细想想觉得还是挺水。 manacher找出所有中心回文串,然后用单调队列扫一下每个位置往左最长和往右最长就行。找位置比较烦不过还是比较好写的。 重点是写出了在windows下拿for循环对拍,虽然异常丑。 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200009; int n, l[maxn], q[maxn], vx[maxn], vy[maxn]; char a[maxn]; void manacher() { l[0] = 1; for (int i = 1, j = 0; i < (n << 1) - 1; ++ i) { int r = ((j + 1) >> 1) + l[j] - 1; int p = i >> 1, q = i - p; l[i] = (r >= q) ? min(r - q + 1, l[(j << 1) - i]) : 0;...
最初以为是splay维护Hash的简单题。顺手开心地敲了个splay还是指针版的。 然后发现tle了。 然后知道了可以暴力重新建串。 然后拿splay暴力重新建串。 然后又tle了。 然后不得已改成了随机线性存取表,过之。 我还是太naive了啊。 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long qw; #define _l (long long int) const int maxn = 200009; const int base = 233; struct str { char a[maxn]; int len; inline str() { len = 0; } inline void read() { scanf("%s", a + 1); len = strlen(a + 1); } inline char operator [](const int& x) const {...
最初以为是水题,直接写个dq交上去不对。 看了下题解才知道是后缀数组。好久不写都快不会写了。 把原串倒过来扔一起排一下就行了。 #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> using namespace std; const int maxn = 60009; int n; int sa[maxn], rk[maxn], ro[maxn], w[maxn], o[maxn]; char a[maxn]; void sufixArray(int n) { memset(w, 0, sizeof(w)); for (int i = 0; i < n; ++ i) ++ w[(int)a[i]]; for (int i = 1; i < 123; ++ i) w[i] += w[i - 1]; for (int i = 0; i < n; ++ i) sa[-- w[(int)a[i]]] = i;...
今天上课讲的题。 做法就直接枚举约数,或者说分解质因数。后者可以预处理到log。 判循环也比较开心。直接用一些奇奇怪怪的字符串的性质就好了。 看来字符串很博大精深啊。 #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long qw; typedef pair <int, qw> hstrv; #define _l (long long int) int _d_; #define readInt(_x_) { \ int& _s_ = _x_; \ while (!isdigit(_d_ = getchar())); \ _s_ = 0; \ while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar())); \ } const int maxn = 500009; const int base = 257; const int hmod = 1000000093;...