题意:给出串A和串集合B={B1,B2,...,Bn},求串A的所有不同子串中不是B中任一串的子串的数目。

思路:把A和B中所有字符串依次拼接在一起,然后构造后缀自动机,计算每个状态的R集合元素的最大值r,然后统计那些r≤length(A)的状态。hdu不卡时间卡空间,这是最郁闷的。。。导致下面的程序只在本地随机数据没发现错误,提交就MLE。

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pb(x) push_back(x)
#define mp(x, y) make_pair(x, y)
#define all(a) (a).begin(), (a).end()
#define mset(a, x) memset(a, x, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(b))
#define cas() int T, cas = 0; cin >> T; while (T --)
template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
typedef long long ll;
typedef pair<int, int> pii; #ifndef ONLINE_JUDGE
#include "local.h"
#endif const int N = 6e5 + 7; int len; //注意空间为 DOUBLE SIZE
class SAM {
public:
void init() {
memset(node, 0, sizeof(node));
sz = last = 0;
node[0].len = 0;
node[0].link = -1;
sz ++;
}
void add(char c) {
int cur = sz ++;
node[cur].len = node[last].len + 1;
node[cur].r = node[cur].len;
int p;
for (p = last; ~p && !node[p].next[c]; p = node[p].link) {
node[p].next[c] = cur;
}
if (p == -1) node[cur].link = 0;
else {
int q = node[p].next[c];
if (node[p].len + 1 == node[q].len) node[cur].link = q;
else {
int clone = sz ++;
node[clone].link = node[q].link;
memcpy(node[clone].next, node[q].next, sizeof(node[q].next));
node[clone].len = node[p].len + 1;
for (; ~p && node[p].next[c] == q; p = node[p].link) {
node[p].next[c] = clone;
}
node[q].link = node[cur].link = clone;
}
}
last = cur;
}
int c[N], p[N];
ll getAns() {
mset(c, 0);
for (int i = 0; i < sz; i ++) c[node[i].len] ++;
for (int i = 1; i <= sz; i ++) c[i] += c[i - 1];
for (int i = 0; i < sz; i ++) p[-- c[node[i].len]] = i;
for (int i = sz - 1; i >= 0; i --) {
int cur = p[i];
if (cur == 0) continue;
umax(node[node[cur].link].r, node[cur].r);
}
ll ans = 0;
for (int i = 1; i < sz; i ++) {
if (node[i].r <= len) ans += node[i].len - node[node[i].link].len;
}
return ans;
}
private:
const static int SZ = 27;
struct State {
int len, link;
int r;
int next[SZ];
};
State node[N];
int sz, last;
};
SAM sam;
char s[N]; int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int n;
cas() {
cin >> n;
sam.init();
for (int i = -1; i < n; i ++) {
scanf("%s", s);
if (i < 0) len = strlen(s);
for (int j = 0; s[j]; j ++) {
sam.add(s[j] - 'a');
}
sam.add(26);
}
printf("Case %d: %I64d\n", ++ cas, sam.getAns());
}
return 0;
}

  

[hdu4416 Good Article Good sentence]后缀自动机SAM的更多相关文章

  1. 【算法】后缀自动机(SAM) 初探

    [自动机] 有限状态自动机的功能是识别字符串,自动机A能识别字符串S,就记为$A(S)$=true,否则$A(S)$=false. 自动机由$alpha$(字符集),$state$(状态集合),$in ...

  2. [转]后缀自动机(SAM)

    原文地址:http://blog.sina.com.cn/s/blog_8fcd775901019mi4.html 感觉自己看这个终于觉得能看懂了!也能感受到后缀自动机究竟是一种怎样进行的数据结构了. ...

  3. SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)

    1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...

  4. 后缀自动机SAM学习笔记

    前言(2019.1.6) 已经是二周目了呢... 之前还是有一些东西没有理解到位 重新写一下吧 后缀自动机的一些基本概念 参考资料和例子 from hihocoder DZYO神仙翻译的神仙论文 简而 ...

  5. 浅谈后缀自动机SAM

    一下是蒟蒻的个人想法,并不很严谨,仅供参考,如有缺误,敬请提出 参考资料: 陈立杰原版课件 litble 某大神 某大神 其实课件讲得最详实了 有限状态自动机 我们要学后缀自动机,我们先来了解一下自动 ...

  6. 后缀自动机(SAM)奶妈式教程

    后缀自动机(SAM) 为了方便,我们做出如下约定: "后缀自动机" (Suffix Automaton) 在后文中简称为 SAM . 记 \(|S|\) 为字符串 \(S\) 的长 ...

  7. 后缀自动机SAM BZOJ 2806

    终于遇到了一道后缀数组不能过 一定要学SAM的题... (看了半个下午+半个上午) 现在总结一下(是给我自己总结..所以只总结了我觉得重要的 .. 看不太懂的话可以To   http://blog.c ...

  8. 【算法】后缀自动机(SAM) 例题

    算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...

  9. 后缀自动机(SAM)速成手册!

    正好写这个博客和我的某个别的需求重合了...我就来讲一讲SAM啦qwq 后缀自动机,也就是SAM,是一种极其有用的处理字符串的数据结构,可以用于处理几乎任何有关于子串的问题,但以学起来异常困难著称(在 ...

随机推荐

  1. copy模块中的copy与deepcopy的区别

    前言 每空闲下来,就觉得以前写的博客很low........也许现在也很low~~~~好吧就当升级版的low吧~~~~ 如果要了解copy与deepcopy的区别,就需要了解Python的存储机制:P ...

  2. 解决vue element table行列不齐问题

    全局加入如下样式即可(app.vue): body .el-table th.gutter{ display: table-cell!important; }

  3. 今天我们来讨论一下CSS3属性中的transition属性;

    transition属性是CSS3属性:顾名思义英文为过渡的意思:主要有四个值与其一一对应:分别是property(CSS属性名称),duration过渡的时长,timimg-function转速曲线 ...

  4. 22-Java-Hibernate框架(二)

    Hibernate的了解.Hibernate的搭建.Hibernate的基本使用流程等内容请阅读21-Java-Hibernate(一) 五.Hibernate的Query查询接口(重中之重) 1.H ...

  5. 面试官:兄弟,说说Java到底是值传递还是引用传递

    二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催.我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊! 说句实在话,离读者 trust you 发给我这段信息已经 ...

  6. Java8新特性(1):Lambda表达式

    Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表.函数主体.返回类型.它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数. ...

  7. python工业互联网监控项目实战4—python opcua

    前面章节我们采用OPC作为设备到上位的信息交互的协议,本章我们介绍跨平台的OPC UA.OPC作为早期的工业通信规范,是基于COM/DCOM的技术实现的,用于设备和软件之间交换数据,最初,OPC标准仅 ...

  8. RT-Thread—STM32—在线升级(Ymodem_OTA、HTTP_OTA)

    概述 本教程主要根据官方推荐的教程进行改编,详细信息请参考OTA Downloader软件包STM32 通用 Bootloader 本例程通过自己实际搭建环境,测试总结. bootloader的制作 ...

  9. ES6新增的 Set 和 WeakSet 是什么玩意?在此揭晓

    现在的章节内容会更加的紧密,如果大家看不懂可以先去看以前的文章,当然看了的忘了,也可以去看一下,这样学习后面的内容才会更加容易. 什么是Set结构 Set是ES6给开发者带来的一种新的数据结构,你可以 ...

  10. 用libevent写的海康摄像头rtsp客户端

    之前一直使用live555作为RTSP的客户端,但其框架臃肿,虽然支持各种格式,但实际中并没有这些需求,关键是其注重于格式的解析,却不注重网络IO,单线程下性能也不高,重新用libevent编写rts ...