Common Substrings

\[Time Limit: 5000 ms\quad Memory Limit: 65536 kB
\]

题意

给出两个字符串,要求两个字符串公共子串长度不小于 \(k\) 的对数。

思路

对 \(S\) 串构建后缀自动机,然后利用 \(v \in u'son\),\(dp[u] += dp[v]\) 求出每个节点的 \(endpos\) 大小。

用 \(T\) 串在自动机上跑最长公共连续子串,假设现在在 \(T\) 串上匹配的最长部分是 \(t\),停在自动机上的 \(p\) 节点。为了防止重复计数,我们现在要求就是的 \(t\) 的所有后缀在 \(S\) 上有多少匹配的位置。

这个计算方法就是 \(\sum dp[i]*(LCS-max(k-1,father.len))\)。在 \(p\) 节点时,\(LCS\) 为我们每次更新的答案 \(res\),接下来往 \(p\) 的 \(father\) 更新时,\(LCS\) 就是 \(i.len\)

比如样例中的

\(xx\\
xx\)

第二个串匹配时,第一次匹配到 \(x\)_ 。第二次匹配到 \(xx\),然后我们继续更新 _\(x\) 的答案。

但是如果每次都暴力向上更新,是会超时的,我们发现只有每个刚刚匹配到的 \(p\) 节点的答案与 \(res\) 有关,而 \(p\) 向上更新的节点的贡献都是固定的,所以我们可以先求出全部的 \(p\) 节点的贡献,然后用 \(cnt[i]\) 表示 \(i\) 节点被底下更新了几次,倒着计算,压缩更新次数。

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout) typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m, k;
int cas, tol, T; struct Sam {
struct Node {
int next[55];
int fa, len;
void init() {
mes(next, 0);
fa = len = 0;
}
} node[maxn];
ll dp[maxn], cnt[maxn];
int sz, last;
void init() {
last = sz = 1;
mes(dp, 0);
node[sz].init();
}
void insert(int k) {
int p = last, np = last = ++sz;
dp[np] = 1;
node[np].init();
node[np].len = node[p].len+1;
for(; p&&!node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p == 0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len+1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len+1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
int tax[maxn], gid[maxn];
void handle() {
for(int i=0; i<=sz; i++) tax[i] = cnt[i] = 0;
for(int i=1; i<=sz; i++) tax[node[i].len]++;
for(int i=1; i<=sz; i++) tax[i] += tax[i-1];
for(int i=1; i<=sz; i++) gid[tax[node[i].len]--] = i;
for(int i=sz; i>=1; i--) {
int u = gid[i];
int fa = node[u].fa;
dp[fa] += dp[u];
}
}
void solve(char *s, int k) {
int len = strlen(s+1);
int p = 1;
ll res = 0, ans = 0;
for(int i=1; i<=len; i++) {
int nst;
if('a'<=s[i] && s[i]<='z') nst = s[i]-'a'+1;
else nst = s[i]-'A'+1+26;
while(p && !node[p].next[nst]) {
p = node[p].fa;
res = node[p].len;
}
if(p == 0) {
p = 1;
res = 0;
} else {
p = node[p].next[nst];
res++;
}
if(res >= k) {
ans += dp[p]*(res - max(node[node[p].fa].len, k-1));
if(node[node[p].fa].len >= k)
cnt[node[p].fa]++;
}
}
for(int i=sz; i>=1; i--) {
int u = gid[i];
ans += dp[u]*cnt[u]*(node[u].len - max(node[node[u].fa].len, k-1));
if(node[node[u].fa].len >= k)
cnt[node[u].fa] += cnt[u];
}
printf("%lld\n", ans);
}
} sam;
char s[maxn], t[maxn]; int main() {
while(scanf("%d", &k), k) {
sam.init();
scanf("%s%s", s+1, t+1);
int slen = strlen(s+1);
for(int i=1; i<=slen; i++) {
int nst;
if('a'<=s[i] && s[i]<='z') nst = s[i]-'a'+1;
else nst = s[i]-'A'+1+26;
sam.insert(nst);
}
sam.handle();
sam.solve(t, k);
}
return 0;
}

Common Substrings POJ - 3415 (后缀自动机)的更多相关文章

  1. POJ 3415 (后缀自动机)

    POJ 3415 Common Substrings Problem : 给两个串S.T (len <= 10^5), 询问两个串有多少个长度大于等于k的子串(位置不同也算). Solution ...

  2. Common Substrings POJ - 3415(长度不小于k的公共子串的个数)

    题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1  sa[i] < len1  和  sa[i-1] < ...

  3. 【SPOJ】Longest Common Substring II (后缀自动机)

    [SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...

  4. POJ 3415 后缀数组

    题目链接:http://poj.org/problem?id=3415 题意:给定2个串[A串和B串],求两个串公共子串长度大于等于k的个数. 思路:首先是两个字符串的问题.所以想用一个'#'把两个字 ...

  5. Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))

    Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...

  6. poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数

    Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 11469   Accepted: 379 ...

  7. LCS - Longest Common Substring(spoj1811) (sam(后缀自动机)+LCS)

    A string is finite sequence of characters over a non-empty finite set \(\sum\). In this problem, \(\ ...

  8. SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

  9. POJ 3518 (后缀自动机)

    POJ 3518 Boring Problem : 给一个串S,询问串S有多个子串出现至少两次且位置不重叠. Solution : 对S串建立后缀自动机,再建立后缀树,dfs一遍统计处每个结点的子树中 ...

随机推荐

  1. Delphi BusinessSkinForm使用说明

    1.先放bsBusinessSkinForm.bsSkinData.bsStoredSkin各一个到窗体上 2.修改bsBusinessSkinForm的SkinData属性为bsSkinData1 ...

  2. C基础 带你手写 redis sds

    前言 - Simple Dynamic Strings  antirez 想统一 Redis,Disque,Hiredis 项目中 SDS 代码, 因此构建了这个项目 https://github.c ...

  3. Java学习:抽象方法和抽象类的使用

    抽象 抽象方法:就是加上abstract关键字,然后去掉大括,直接分号结束.抽象类:抽象方法所在的类,必须是抽象类才行.在class之前写上abstract即可. 如何使用抽象类和抽象方法: 1.不能 ...

  4. mycat在windows环境下安装和启动

    1.下载从如下地址下载mycat的安装包: http://www.mycat.io/ eg:Mycat-server-1.6.6.1-release-20181031195535-win.tar.gz ...

  5. 《PHP7底层设计与源码实现》学习笔记1——PHP7的新特性和源码结构

    <PHP7底层设计与源码实现>一书的作者陈雷亲自给我们授课,大佬现身!但也因此深感自己基础薄弱,遂买了此书.希望看完这本书后,能让我对PHP7底层的认识更上一层楼.好了,言归正传,本书共1 ...

  6. 整理:WPF中XmlDataProvider的用法总结

    原文:整理:WPF中XmlDataProvider的用法总结 一.目的:了解XmlDataProvider中绑定数据的方法 二.绑定方式主要有三种: 1.Xaml资源中内置: <!--XPath ...

  7. Kafka Streams的Data Types and Serialization

    Avro <repositories> <repository> <id>confluent</id> <url>http://packag ...

  8. 自定义 Windows 右键菜单项

    注:本文涉及到注册表操作,不认识请不要随意修改! 右键菜单项储存在注册表 HKEY_CLASSES_ROOT 中,一般各种程序的右键菜单项都可以在此项下面找到: 添加右键菜单项 右键单击 shell, ...

  9. VS 发布MVC网站缺少视图

    mvc项目发布之后会有一些视图文件缺少,不包含在发布文件中,虽然可以直接从项目文件中直接拷贝过来,但还是想知道是什么原因,发布文件好像没有找到哪里有设置这个的地方 把生成操作:无-改成内容即可 原文

  10. J2EE 练习题 - JSON HTTP Service

    J2EE 练习题 - JSON HTTP Service 1 要求 2 示例代码 2.1 Server 端 2.2 客户端 - Java 1 要求 在 Tomcat 上布署一个 HTTP Servic ...