POJ 3518 (后缀自动机)
POJ 3518 Boring
Problem : 给一个串S,询问串S有多个子串出现至少两次且位置不重叠。
Solution : 对S串建立后缀自动机,再建立后缀树,dfs一遍统计处每个结点的子树中最长节点max和最短节点min。枚举一遍后缀自动机的节点,那么对于其对应后缀的长度要求为小于等于max - min。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1000008;
const int INF = 2000000008;
struct edge
{
int u, v, nt;
};
struct suffix_automanon
{
int nt[N][26], fail[N], a[N], qmin[N], qmax[N];
int tot, last, root;
int lt[N], sum;
int p, q, np, nq;
edge eg[N << 1];
void add(int u, int v)
{
eg[++sum] = (edge){u, v, lt[u]}; lt[u] = sum;
}
int newnode(int len)
{
for (int i = 0; i < 26; ++i) nt[tot][i] = -1;
fail[tot] = -1; a[tot] = len; qmax[tot] = 0; qmin[tot] = INF;
lt[tot] = 0;
return tot++;
}
void clear()
{
tot = 0;
root = last = newnode(0);
}
void insert(int ch)
{
p = last; np = last = newnode(a[p] + 1); qmin[np] = qmax[np] = a[np];
for (; ~p && nt[p][ch] == -1; p = fail[p]) nt[p][ch] = np;
if (p == -1) fail[np] = root;
else
{
q = nt[p][ch];
if (a[p] + 1 == a[q]) fail[np] = q;
else
{
nq = newnode(a[p] + 1);
for (int i = 0; i < 26; ++i) nt[nq][i] = nt[q][i];
fail[nq] = fail[q];
fail[q] = fail[np] = nq;
for (; ~p && nt[p][ch] == q; p = fail[p]) nt[p][ch] = nq;
}
}
}
void dfs(int u)
{
for (int i = lt[u]; i; i = eg[i].nt)
{
// cout << u << " " << eg[i].v << endl;
int v = eg[i].v;
dfs(v);
qmax[u] = max(qmax[u], qmax[v]);
qmin[u] = min(qmin[u], qmin[v]);
}
}
void solve()
{
long long ans = 0;
for (int i = 1; i < tot; ++i) add(fail[i], i);
dfs(root);
// for (int i = 1; i < tot; ++i) cout << qmin[i] << " " << qmax[i] << endl;
for (int i = 1; i < tot; ++i)
{
int len = qmax[i] - qmin[i];
if (len > a[fail[i]]) ans += min(a[i], len) - a[fail[i]];
}
cout << ans << endl;
}
}sam;
int main()
{
string s;
while (cin >> s)
{
if (s == "#") break;
sam.clear();
for (int i = 0, len = s.length(); i < len; ++i)
sam.insert(s[i] - 'a');
sam.solve();
}
}
POJ 3518 (后缀自动机)的更多相关文章
- POJ 3415 (后缀自动机)
POJ 3415 Common Substrings Problem : 给两个串S.T (len <= 10^5), 询问两个串有多少个长度大于等于k的子串(位置不同也算). Solution ...
- Boring counting HDU - 3518 后缀自动机
题意: 对于给出的字符串S, 长度不超过1000, 求其中本质不同的子串的数量, 这些子串满足在字符串S中出现了至少不重合的2次 题解: 将串放入后缀自动机中然后求出每一个节点对应的子串为后缀的子串出 ...
- POJ - 1743 后缀自动机
POJ - 1743 顺着原字符串找到所有叶子节点,然后自下而上更新,每个节点right的最左和最右,然后求出答案. #include<cstdio> #include<cstrin ...
- POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示
http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图 ...
- UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)
题目大意: 给出一个长度为N的字符串,求其字典序最小的循环同构. N<=10W. 算法讨论: 算法一.最小表示法.定义题. 算法二.后缀自动机. Codes: #include <iost ...
- POJ.2774.Long Long Message/SPOJ.1811.LCS(后缀自动机)
题目链接 POJ2774 SPOJ1811 LCS - Longest Common Substring 确实比后缀数组快多了(废话→_→). \(Description\) 求两个字符串最长公共子串 ...
- poj 1743 Musical Theme 后缀自动机/后缀数组/后缀树
题目大意 直接用了hzwer的题意 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题."主题&qu ...
- Common Substrings POJ - 3415 (后缀自动机)
Common Substrings \[ Time Limit: 5000 ms\quad Memory Limit: 65536 kB \] 题意 给出两个字符串,要求两个字符串公共子串长度不小于 ...
- POJ - 2774 Long Long Message (后缀数组/后缀自动机模板题)
后缀数组: #include<cstdio> #include<algorithm> #include<cstring> #include<vector> ...
随机推荐
- yum 安装报错:*epel: mirrors.aliyun.comError: xzcompressionnot available
环境背景:epel源下载地址: http://mirrors.aliyun.com/Centos内核内核版本[root@nfs01 ~]# uname -r2.6.32-642.el6.x86_64= ...
- Java中static修饰符
public class StaticTest { static int i ; static int m=30; int j ; int k=25; static{ i=10; System.out ...
- 后缀数组 (Suffix Array) 学习笔记
\(\\\) 定义 介绍一些写法和数组的含义,首先要知道 字典序 . \(len\):字符串长度 \(s\):字符串数组,我们的字符串存储在 \(s[0]...s[len-1]\) 中. \(suff ...
- Android开发使用的常见第三方框架汇总
本文转载:http://blog.csdn.net/liuhaomatou/article/details/44857005 1.volley 项目地址 https://github.com/sman ...
- 架构(Architecture)随想
架构(Architecture)的意义: 先不要看什么是架构,先看下architect是什么,没有错,它是建筑师,在一块空地上build高楼大厦的人,它是一个designer,设计好整个大楼,也是一个 ...
- leetcode_951. Flip Equivalent Binary Trees_二叉树遍历
https://leetcode.com/problems/flip-equivalent-binary-trees/ 判断两棵二叉树是否等价:若两棵二叉树可以通过任意次的交换任意节点的左右子树变为相 ...
- Python 保留n位小数
输出a, b 且保留三位小数 a = 2.3456 b = 2.0000 三种方法: round(a, 3)('%.3f' % a)Decimal(a).quantize(Decimal('0.000 ...
- Axure 9 面板折叠显示隐藏
1 首先放置一个面板1作为点击事件: 2 另外一个面板2或者其他组建,将其设置为动态面板,然后隐藏 3 给面板1添加如下事件,即可: 4 我们点击面板1,可以实现展开隐藏面板2的动态效果
- numpy add
在numpy中,'+' 和add 是一样的 np.add(x1, x2) x1+x2 有种特殊情况需要注意,x1和x2的shape不一样的加法: 两个shape不一样的array相加后会变成一个com ...
- java正则表达式进阶运用20181023
直接上代码. package org.jimmy.autotranslate20181022.test; import java.util.regex.Matcher; import java.uti ...