POJ 3415 (后缀自动机)
POJ 3415 Common Substrings
Problem : 给两个串S、T (len <= 10^5), 询问两个串有多少个长度大于等于k的子串(位置不同也算)。
Solution :最开始的想法是将S串和T串先后插入后缀自动机,统计出每个节点对应串的出现次数,不过这种做法被卡空间了。
第二种想法是只将S串插入后缀自动机,建立后缀树,统计出每个节点对应串的出现次数,在统计出每个节点的所有父亲节点的出现次数之和。之后将T串在后缀自动机上进行匹配,假设当前T串在p节点匹配成功,且匹配成功长度为len,那么对答案的贡献就是p节点所有长度超过k的父亲节点,再加上当前节点中长度超过k但不超过
tmp的串。
#include <iostream>
#include <string>
using namespace std;
const int N = 200008;
struct edge
{
int v, nt;
};
struct Suffix_Automanon
{
int nt[N][60], a[N], fail[N];
int tot, last, root;
int lt[N], sum;
int p, q, np, nq;
int cnt[N];
long long f[N];
edge eg[N];
int newnode(int len)
{
for (int i = 0; i < 60; ++i) nt[tot][i] = -1;
fail[tot] = -1; cnt[tot] = f[tot] = lt[tot] = 0; a[tot] = len;
return tot++;
}
void clear()
{
tot = sum = 0;
last = root = newnode(0);
}
void add(int u, int v)
{
eg[++sum] = (edge){v, lt[u]}; lt[u] = sum;
}
void insert(int ch)
{
p = last; np = last = newnode(a[p] + 1); cnt[np] = 1;
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 < 60; ++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)
{
dfs(eg[i].v);
cnt[u] += cnt[eg[i].v];
}
}
void dfs(int u, int k)
{
for (int i = lt[u]; i; i = eg[i].nt)
{
if (u != root && k <= a[u])
{
f[eg[i].v] += f[u] + (a[u] - max(k, a[fail[u]] + 1) + 1) * cnt[u];
}
dfs(eg[i].v, k);
}
}
void build(int k)
{
for (int i = 1; i < tot; ++i) add(fail[i], i);
dfs(root);
dfs(root, k);
}
void solve(const string &s, int k)
{
int p = root, tmp = 0;
long long ans = 0;
for (int i = 0, len = s.length(); i < len; ++i)
{
int ch = s[i] - 'A';
if (~nt[p][ch]) p = nt[p][ch], tmp++;
else
{
for (; ~p && nt[p][ch] == -1; p = fail[p]);
if (p == -1) p = root, tmp = 0;
else
{
tmp = a[p] + 1;
p = nt[p][ch];
}
}
if (p != root)
{
ans += f[p];
if (tmp >= k && k <= a[p]) ans += (min(a[p], tmp) - max(k, a[fail[p]] + 1) + 1) * cnt[p];
}
}
cout << ans << endl;
}
}sam;
int main()
{
int n; string s, t;
while (cin >> n >> s >> t)
{
sam.clear();
for (int i = 0, len = s.length(); i < len; ++i)
sam.insert(s[i] - 'A');
sam.build(n);
sam.solve(t, n);
}
}
POJ 3415 (后缀自动机)的更多相关文章
- POJ 3415 后缀数组
题目链接:http://poj.org/problem?id=3415 题意:给定2个串[A串和B串],求两个串公共子串长度大于等于k的个数. 思路:首先是两个字符串的问题.所以想用一个'#'把两个字 ...
- POJ 3518 (后缀自动机)
POJ 3518 Boring Problem : 给一个串S,询问串S有多个子串出现至少两次且位置不重叠. Solution : 对S串建立后缀自动机,再建立后缀树,dfs一遍统计处每个结点的子树中 ...
- POJ - 2774~POJ - 3415 后缀数组求解公共字串问题
POJ - 2774: 题意: 求解A,B串的最长公共字串 (摘自罗穗骞的国家集训队论文): 算法分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长 公共子串等价于求 ...
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11469 Accepted: 379 ...
- POJ - 1743 后缀自动机
POJ - 1743 顺着原字符串找到所有叶子节点,然后自下而上更新,每个节点right的最左和最右,然后求出答案. #include<cstdio> #include<cstrin ...
- POJ 3415 后缀数组+单调栈
题目大意: 给定A,B两种字符串,问他们当中的长度大于k的公共子串的个数有多少个 这道题目本身理解不难,将两个字符串合并后求出它的后缀数组 然后利用后缀数组求解答案 这里一开始看题解说要用栈的思想,觉 ...
- Common Substrings POJ - 3415 (后缀自动机)
Common Substrings \[ Time Limit: 5000 ms\quad Memory Limit: 65536 kB \] 题意 给出两个字符串,要求两个字符串公共子串长度不小于 ...
- POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示
http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图 ...
- POJ 3415 Common Substrings(后缀数组 + 单调栈)题解
题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...
随机推荐
- solr之~模糊查询【转】
solr之~模糊查询 有的时候,我们一开始不可能准确地知道搜索的关键字在 Solr 中查询出的结果是什么,因此,Solr 还提供了几种类型的模糊查询.模糊匹配会在索引中对关键字进行非精确匹配.例如,有 ...
- ABP教程(二)- 将ABP在本地运行起来
上一篇 我们介绍了什么是ABP,这一篇我们通过原作者的”简单任务系统”例子,演示如何运用ABP开发项目 从模板创建空的web应用程序 ABP提供了一个启动模板用于新建的项目(尽管你能手动地创建项目并且 ...
- java 线程池第一篇 之 ThreadPoolExcutor
一:什么是线程池? java 线程池是将大量的线程集中管理的类,包括对线程的创建,资源的管理,线程生命周期的管理.当系统中存在大量的异步任务的时候就考虑使用java线程池管理所有的线程.减少系统资源的 ...
- darknet在windows上的安装编译与使用
darknet(https://github.com/pjreddie/darknet)实现了YOLO网络模型,能快速准确识别多达9000种物体.但其在windows系统上的安装却并非一帆风顺,本文进 ...
- 手动将Excel数据导入SQL
1. 右键点击数据库名称,Tasks --> Import Data... 2. Choose Data Source:MicroSoft Excel,选择Excel文件和Excel版本.Exc ...
- PowerShell让系统可以执行.ps1文件,开机,关机,在线时间 , Function自定义函数
Function Get-ComputerUptimeHistory { $q=' <QueryList> <Query Id="0" Path="Sy ...
- 手机信号强度单位:dBm 和 asu
介绍 首先明确:dBm 和 asu 是两个独立的单位,它们的换算关系不唯一. 在 2G 网络下:dBm = -113+2*asu在 4G 网络下:dBm = -140+asu dBm 和 asu 都用 ...
- Seating Arrangement
1997: Seating Arrangement Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 543 Solved: ...
- 09C++指针
指针 6.1 指针的概念 请务必弄清楚一个内存单元的地址与内存单元的内容这两个概念的区别.在程序中一般是通过变量名来对内存单元进行存取操作的.其实程序经过编译以后已经将变量名转换为变量的地址,对变量值 ...
- hive纯命令行
vim /etc/profileexport HIVE_HOME=/export/servers/hive...export PATH=:$HIVE_HOME/bin:$PATH 前台启动hive:h ...