http://www.lydsy.com/JudgeOnline/problem.php?id=3926

广义后缀自动机的例题,感觉广义后缀自动机好恶心。。。

广义后缀自动机是对一个trie建立的后缀自动机,能识别trie上的所有子串。right集合代表的是trie树上的节点集合。

具体做法是把last移到“在trie树上要添加节点的节点”在后缀自动机的状态节点上,然后套插入模板。

插入模板的运行过程跟对一个串建立后缀自动机有些不同。

假设插入w,首先np节点的\(|Right|\)可以不再等于1,而且如果last存在w的转移函数,特判一下转移到的点的maxlen是否为last的maxlen+1。如果是,直接把last移到这个点就行了。

不移动也可以,这样会新建一个np节点,np->par为last->go,相当于把np和last->go看成一个点。

如果转移到的点的maxlen大于last的maxlen,那么在插入模板里需要新建一个nq节点,nq的maxlen为last的maxlen+1。

同时插入模板里还要把np和q的par指针指向nq。注意这里np和nq的right集合是完全相同的!但是np->par=nq,不符合后缀自动机里“真包含”的定义,不过我们还是可以把这里的np和nq看成一个点。

其他情况跟一般的后缀自动机构造一样。

最后把last移向np,如果np和nq的right集合完全相同,就把它们一起看成一个“大点”,last在np上没有某个转移函数就跳到nq上看有没有这个转移函数,相当于这个“大点”的转移函数是np和nq的转移函数的并集。

时空复杂度还是\(O(n)\)。

在mrazer神犇的帮助下终于理解了qwq

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; ll ans = 0;
struct State {
State *par, *go[10];
int val;
State(int _num) : val(_num) {par = 0; memset(go, 0, sizeof(go));}
} *root, *last; void extend(int w) {
if (last->go[w] && last->go[w]->val == last->val + 1) {
last = last->go[w];
return;
}
State *p = last;
State *np = new State(p->val + 1);
while (p && p->go[w] == 0)
p->go[w] = np, p = p->par;
if (p == 0) np->par = root;
else {
State *q = p->go[w];
if (p->val + 1 == q->val) np->par = q;
else {
State *nq = new State(p->val + 1);
memcpy(nq->go, q->go, sizeof(q->go));
nq->par = q->par;
q->par = np->par = nq;
while (p && p->go[w] == q)
p->go[w] = nq, p = p->par;
}
}
last = np; ans += np->val - np->par->val;
} const int N = 100003;
int n, c, cnt = 0, point[N], du[N], col[N];
struct node {int nxt, to;} E[N << 1];
void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;} void dfs(int x, int fa) {
extend(col[x]);
State *now = last;
for (int i = point[x], v = E[i].to; i; v = E[i = E[i].nxt].to)
if (v != fa) {
dfs(v, x);
last = now;
}
} int main() {
root = last = new State(0);
scanf("%d%d", &n, &c);
for (int i = 1; i <= n; ++i) scanf("%d", col + i);
int u, v;
for (int i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
ins(u, v); ins(v, u);
++du[u]; ++du[v];
} for (int i = 1; i <= n; ++i)
if (du[i] == 1)
last = root, dfs(i, -1);
printf("%lld\n", ans);
return 0;
}

下面的是讨论版的没有任何多余的节点的广义后缀自动机(及不需要把两个点理解成一个大点),感觉自己好闲啊qwq

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; ll ans = 0;
struct State {
State *par, *go[10];
int val;
State(int _num) : val(_num) {par = 0; memset(go, 0, sizeof(go));}
} *root, *last; void extend(int w) {
if (last->go[w] && last->go[w]->val == last->val + 1) {
last = last->go[w];
return;
}
State *p = last;
State *np = new State(p->val + 1);
while (p && p->go[w] == 0)
p->go[w] = np, p = p->par;
if (p == 0) np->par = root;
else {
State *q = p->go[w];
if (p->val + 1 == q->val) np->par = q;
else if (p != last) {
State *nq = new State(p->val + 1);
memcpy(nq->go, q->go, sizeof(q->go));
nq->par = q->par;
q->par = np->par = nq;
while (p && p->go[w] == q)
p->go[w] = nq, p = p->par;
} else {
memcpy(np->go, q->go, sizeof(q->go));
np->par = q->par;
q->par = np;
while (p && p->go[w] == q)
p->go[w] = np, p = p->par;
last = np; return;
}
}
last = np; ans += last->val - last->par->val;
} const int N = 100003;
int n, c, cnt = 0, point[N], du[N], col[N];
struct node {int nxt, to;} E[N << 1];
void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;} void dfs(int x, int fa) {
extend(col[x]);
State *now = last;
for (int i = point[x], v = E[i].to; i; v = E[i = E[i].nxt].to)
if (v != fa) {
dfs(v, x);
last = now;
}
} int main() {
root = last = new State(0);
scanf("%d%d", &n, &c);
for (int i = 1; i <= n; ++i) scanf("%d", col + i);
int u, v;
for (int i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
ins(u, v); ins(v, u);
++du[u]; ++du[v];
} for (int i = 1; i <= n; ++i)
if (du[i] == 1)
last = root, dfs(i, -1);
printf("%lld\n", ans);
return 0;
}

【BZOJ 3926】【ZJOI 2015】诸神眷顾的幻想乡的更多相关文章

  1. BZOJ 3926 && ZJOI 2015 诸神眷顾的幻想乡 (广义后缀自动机)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MB Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽 ...

  2. 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 974  Solved: 573 Descriptio ...

  3. ZJOI 2015 诸神眷顾的幻想乡

    题目描述 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常 ...

  4. BZOJ 3926 诸神眷顾的幻想乡

    BZOJ 3926 诸神眷顾的幻想乡 开始看错题看成了每个点度数不超过20 后来翻了翻题解原来看错题的不止我一个 既然叶子数量不超过20,考虑树上的任何一条路径,以任何点为根时,如果它不是一条从上到下 ...

  5. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][S ...

  6. 字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][St ...

  7. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 [广义后缀自动机 Trie]

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1124  Solved: 660[Submit][S ...

  8. BZOJ 3926: [Zjoi20150]诸神眷顾的幻想乡

    3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 438  Solved: 273 Descripti ...

  9. BZOJ3926&&lg3346 ZJOI诸神眷顾的幻想乡(广义后缀自动机)

    BZOJ3926&&lg3346 ZJOI诸神眷顾的幻想乡(广义后缀自动机) 题面 自己找去 HINT 我们可以把题目拆解成几个部分,首先我们手玩一个结论,从所有的叶子节点出发,遍历整 ...

  10. 【BZOJ3926】诸神眷顾的幻想乡(后缀自动机)

    [BZOJ3926]诸神眷顾的幻想乡(后缀自动机) 题面 BZOJ 题解 广义后缀自动机啦 求多个串的不同子串个数? 当然是后缀自动机,最后只要把\(longest-parent.longest\)求 ...

随机推荐

  1. 关于tomcat启动没有进行编译或者编译报错的问题

    关于tomcat 的问题 如果项目没有编译 解决方案:1: 把项目刷新一下 然后Clean一下,之后等待右下角编译完成100%2: 有可能tomcat conf 里的配置文件的错误 进入查看下3: 如 ...

  2. 用CSS让文字居于div的底部

    css对文字的布局上没有靠容器底部对齐的参数,目前使用的一个不错的方法也比较好.就是用position属性来解决,看下面的代码,用position的相对和绝对定位功能也轻松的实现了,文字靠近div低部 ...

  3. (转)C++中返回对象的情形及RVO

    http://www.cnblogs.com/xkfz007/archive/2012/07/21/2602110.html 之前有文章介绍过临时对象和返回值优化RVO方面的问题.见此处. 在C++中 ...

  4. mr本地运行的几种模式

    MR程序的几种提交运行模式 本地模型运行 1/在windows的eclipse里面直接运行main方法,就会将job提交给本地执行器localjobrunner执行 ----输入输出数据可以放在本地路 ...

  5. 如何创建一个要素数据类 IField,IFieldEdit,IFields,IFieldsEditI,GeometryDef,IGeometryDefEdit接口

    如何创建一个要素数据类 创建要素类用到了IFeatureWorkspace.CreateFeatureClass方法,在这个方法中有众多的参数,为了满足这些参数,我们要学习和了解下面的接口. IFie ...

  6. (简单) CF 44D Hyperdrive,数学。

    In a far away galaxy there are n inhabited planets, numbered with numbers from 1 to n. They are loca ...

  7. centos 7用ss命令来查看端口占用和对应进程

    mysqld进程在监听4567端口,进程id是2593:# ss -lnp|grep 4567tcp    LISTEN     0      128                    *:456 ...

  8. 内核kconfig语法及原理

    语法 http://www.cnblogs.com/AP0904225/p/5967979.html 目前自己用过 一.菜单 menu "desc" endmenu 二.可配菜单 ...

  9. Jetty实战之 嵌入式Jetty运行Servlet

    http://blog.csdn.net/kongxx/article/details/7230080 Jetty实战之 嵌入式Jetty运行Servlet 分类:JettyJava (19530)  ...

  10. (中等) POJ 1191 棋盘分割,DP。

    Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次 ...