常见的子串
时间限制: 5000MS   内存限制: 65536K
提交总数: 11942   接受: 4051

描述

字符串T的子字符串被定义为:

Ťķ)= Ť  Ť  1 ... Ť I
+ K
 -1,1≤  ≤ I + K -1≤| T |。

给定两个字符串AB和一个整数K,我们定义S,一组三元组(ijk):

S = {(ijk)| ķ ≥ ķķ)= Ĵķ)}。

你要给的价值| S | 特定ķ

输入

输入文件包含几个数据块。对于每个块,第一行包含一个整数ķ,随后包含字符串两行分别。输入文件以K =
0 结尾。

1≤| A |,| B | ≤10 5

1≤ ķ ≤ 分钟 {| A |,| B |} AB的

字符都是拉丁字母。

产量

对于每种情况,输出一个整数| S |。

示例输入

2
aababaa
abaabaa
1
XX
XX
0

示例输出

22

蜜汁翻译。。额不要在意

挺难的一题,弱弱的我码了一个中午

首先后缀数组双串匹配,同样的操作,两串链接用一字符隔开,跑一遍sa

重点就是如何求出公共前缀大于等于K的子串数

首先如果lcp(i,j) = len 【len >k】那么len - 1也满足

所以对于lcp(i,j),它的贡献是len - k + 1

我们利用height数组分组,每一个组内的AB串都可以匹配,统计答案即可

但这样会T,因为这样做其实是O(n^2)的

怎么办呢?

我们需要维护一个单调栈,扫两次

第一次:对于每个A,统计它前面的B对于答案的贡献

我们知道两串在height数组之间的最小值即为其最长公共前缀长度,

对于A前第一个B之后的一个最小值,一定会影响到之前左右的B,但是B与B之间的最小值只会影响到前面的B而不影响到后面的B

因此我们维护一个单调递增单调栈,如果当前height比栈顶小,那么栈顶所对应的那些后缀会受到此height的影响【 因为之前的B到后面的A一定会跨过这个地方,而这个地方height较小】,就合并栈顶【注意是合并】

看代码吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
char s[maxn],B[maxn];
int sa[maxn],rank[maxn],height[maxn],t1[maxn],t2[maxn],c[maxn],n,m,K,lA;
void SA(){
int *x = t1,*y = t2;
for (int i = 0; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;
for (int i = 1; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1){
int p = 0;
for (int i = n - k + 1; i <= n; i++) y[++p] = i;
for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
for (int i = 0; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[y[i]]]++;
for (int i = 1; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
swap(x,y);
p = 1; x[sa[1]] = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p;
if (p >= n) break;
m = p;
}
REP(i,n) rank[sa[i]] = i;
int k = 0;
REP(i,n){
if (k) k--;
int j = sa[rank[i] - 1];
while (s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
}
pair<int,int> st[maxn];
int top;
LL ans;
void solve(){
LL sum = 0; top = 0;
for (int i = 2; i <= n; i++){
if (height[i] < K){
top = 0; sum = 0;
}else {
int num = 0;
if (sa[i - 1] > lA + 1) num++,sum += height[i] - K + 1;
while (top && height[i] <= st[top].first){
sum -= st[top].second * (st[top].first - height[i]);
num += st[top--].second;
}
st[++top] = make_pair(height[i],num);
if (sa[i] <= lA) ans += sum;
}
}
top = 0; sum = 0;
for (int i = 2; i <= n; i++){
if (height[i] < K){
top = 0; sum = 0;
}else {
int num = 0;
if (sa[i - 1] <= lA) num++,sum += height[i] - K + 1;
while (top && height[i] <= st[top].first){
sum -= st[top].second * (st[top].first - height[i]);
num += st[top--].second;
}
st[++top] = make_pair(height[i],num);
if (sa[i] > lA + 1) ans += sum;
}
}
}
int main(){
while (K = RD()){
scanf("%s",s + 1); lA = strlen(s + 1); strcat(s + 1,"#");
scanf("%s",B + 1); strcat(s + 1,B + 1);
ans = 0; m = 256; n = strlen(s + 1);
SA();
solve();
printf("%lld\n",ans);
}
return 0;
}

POJ3415 Common Substrings 【后缀数组 + 单调栈】的更多相关文章

  1. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  2. POJ3415 Common Substrings(后缀数组 单调栈)

    借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...

  3. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  4. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  5. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  6. poj3415 Common Substrings (后缀数组+单调队列)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9414   Accepted: 3123 Description A sub ...

  7. 【BZOJ-3238】差异 后缀数组 + 单调栈

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status] ...

  8. BZOJ_3879_SvT_后缀数组+单调栈

    BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...

  9. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  10. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

随机推荐

  1. 解决百度编辑器ueditor插入视频网址保存不了问题

    问题:如下图,在百度编辑器中插入视频,视频网址可以识别,但是提交内容后视频却显示不了. 解决:这个问题主要是编辑器中会过滤一些html标签,所以可以给标签添加白名单. 修改 ueditor.confi ...

  2. BC追踪

    项目又要开始改造了,记录一下改造过程中碰到的坑和解决思路,避免以后回头看看自己的笔记都不知道写了什么. (一)敏感信息混淆 (二)活用ComponentScan (三)Swagger配置多项目共用 ( ...

  3. 如何导入XML数据 (python3.6.6区别于python2 环境)

    1.在python2中 代码如下图: 放在python3 环境下执行,将出现如下错误: 原因: python2中形如myTree.keys()[0]这样的写法是没有问题的,因为myTree.keys( ...

  4. Java基础——内部类

    一.什么是内部类 将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类 内部类所在的类在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$In ...

  5. LINQ查询操作符

    ·First - 返回集合中的第一个元素:不延迟 ·FirstOrDefault - 返回集合中的第一个元素(如果没有则返回默认值):不延迟 ·Last - 返回集合中的最后一个元素:不延迟 ·Las ...

  6. LeetCode:11. ContainerWithWater(Medium)

    原题链接:https://leetcode.com/problems/container-with-most-water/description/ 题目要求:给定n个非负整数a1,a2,...,an  ...

  7. Java - 问题集 - linux下,jar: command not found

    linux下的找不到jar命令解决方法如下: 1. 确认jdk是否已安装 2. 检查jdk环境变量是否已设置,并且确认该设置已生效 3. 1,2两步均正常时,建立jar的软链接 # cd /usr/b ...

  8. 步骤1:JMeter 录制脚本接口测试

    JMeter 常用测试方法简介 1.下载安装 http://jmeter.apache.org/download_jmeter.cgi 安装JDK,配置环境变量JAVA_HOME. 系统要求:JMet ...

  9. QSS 的选择器

    本文连接地址:http://www.qtdebug.com/QSS-Selector.html 选择器决定了 style sheet 作用于哪些 Widget,QSS 支持 CSS2 定义的所有选择器 ...

  10. Unity和Lua交互

    用lua就表示项目用到了热更新,通常每次热更新都会从服务器获取最新的lua脚本放到Android/ios设备的本地目录下,但是lua应该放到哪个目录下呢,这里就先说说lua里面的路径问题 1.不可以放 ...