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. 条形图(diagrams)

    条形图(diagrams) 题目描述 小 虎刚上了幼儿园,老师让他做一个家庭作业:首先画3行格子,第一行有3个格子,第二行有2个格子,第三行有3个格子.每行的格子从左到右可以放棋子,但要 求除第一行外 ...

  2. 微信公众号系列 --- ionic在IOS的键盘弹出问题

    在使用ionic开发IOS系统微信的时候会有一个苦恼的问题,填写表单的时候键盘会挡住输入框,其实并不算什么大问题,只要用户输入一个字就可以立刻看见输入框了. 可惜的是,有些客户是不讲理的,他才不管这个 ...

  3. Size Balanced Tree(SBT) 模板

    首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...

  4. 读取excel数据 到 datagrid 出现 找不到可安装的ISAM

    读取excel数据 到 datagrid 出现:找不到可安装的ISAM       错误: 实在没有办法了 就仔细的查看了 一下数据链接字符串: string strConn = "Prov ...

  5. 高效PHP编程

    1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍.   当然了,这个测试方法需要在十万级以上次执行,效果才明显.   其实静态方法和非静 ...

  6. c语言学习基础:[1]开发工具介绍

    标签:c语言 1 2 3 4 分步阅读 学习编程语言的童鞋们一开始接触到的最多的估计就是C语言了,其次才是什么java.c++等,可以说学习c语言是我们走向编程世界的一座桥梁,学好它,对于我们学习和研 ...

  7. MySql绿色版安装过程记录

    作为程序猿,要多动手,周末趁着有空且笔记本刚刚装了系统,所以就配置了下绿色版的MySQL. 多动手,多动手,多动手. 多总结,多总结,多总结. 以下为正文: 一.下载MySQL绿色版: 1.这个地址: ...

  8. angularJS 系列(一)

    angularJS 中 $scope 的原型 和 原型继承之间的细微差别是什么? 参考:http://stackoverflow.com/questions/14049480/what-are-the ...

  9. AppServ设置虚拟主机 及域名连接

    1: 安装好AppServ2.5.9软件,官网是:http://www.appservnetwork.com/ ,2.59下载地址是:http://nchc.dl.sourceforge.net/so ...

  10. c++异常处理第四篇---不使用try catch语句,使用Loki::ScopeGuard

    转载:神奇的Loki::ScopeGuard 2011-07-05 12:52:05 分类: C/C++ 转载:http://blog.csdn.net/fangqu/article/details/ ...