题目链接:https://vjudge.net/problem/POJ-3415

Common Substrings
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12240   Accepted: 4144

Description

A substring of a string T is defined as:

T(ik)=TiTi+1...Ti+k-1, 1≤ii+k-1≤|T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

S = {(ijk) | kKA(ik)=B(jk)}.

You are to give the value of |S| for specific AB and K.

Input

The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.

1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.

Output

For each case, output an integer |S|.

Sample Input

2
aababaa
abaabaa
1
xx
xx
0

Sample Output

22
5

Source

题意:

给出两个字符串,求有多少对长度不小于k的公共子串,子串相同但位置不同也单独算作一对。

题解:

1.将两个字符串拼接在一起,中间用分隔符隔开,得到新串。并且需要记录每个位置上的字符(后缀)属于哪一个字符串。

2.求出新串的后缀数组。可知sa[i]和sa[j]的最长公共前缀为:min(height[k])i+1<=k<=j。

3.根据第二点,可以枚举sa数组,当遇到A串时,就先放着,当遇到B串时,就往前统计与所有A串的最长公共前缀,假如为len,那么就能增加len-k+1个公共前缀了。由于是按着sa的顺序枚举下去的,所以对于在B串下面的A串是没有统计到的,所以需要二次统计:把A串当成B串, B串当成A串,然后再进行统计,方可无遗漏。

4.往前统计时需要用到单调栈。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 2e5+; int id[MAXN];
int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
int t1[MAXN], t2[MAXN], c[MAXN]; bool cmp(int *r, int a, int b, int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
} void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
for(i = ; i<m; i++) c[i] = ;
for(i = ; i<n; i++) c[x[i] = str[i]]++;
for(i = ; i<m; i++) c[i] += c[i-];
for(i = n-; i>=; i--) sa[--c[x[i]]] = i;
for(j = ; j<=n; j <<= )
{
p = ;
for(i = n-j; i<n; i++) y[p++] = i;
for(i = ; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j; for(i = ; i<m; i++) c[i] = ;
for(i = ; i<n; i++) c[x[y[i]]]++;
for(i = ; i<m; i++) c[i] += c[i-];
for(i = n-; i>=; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y);
p = ; x[sa[]] = ;
for(i = ; i<n; i++)
x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++; if(p>=n) break;
m = p;
} int k = ;
n--;
for(i = ; i<=n; i++) Rank[sa[i]] = i;
for(i = ; i<n; i++)
{
if(k) k--;
j = sa[Rank[i]-];
while(str[i+k]==str[j+k]) k++;
height[Rank[i]] = k;
}
} int Stack[MAXN][], top;
LL cal(int k, int len, int flag)
{
LL sum = , tmp = ;
top = ;
for(int i = ; i<=len; i++)
{
if(height[i]<k)
tmp = top = ;
else
{
int cnt = ;
if(id[sa[i-]]==flag)
tmp += height[i]-k+, cnt++;
while(top> && height[i]<=Stack[top-][])
{
tmp -= 1LL*Stack[top-][]*(Stack[top-][]-height[i]);
cnt += Stack[top-][];
top--;
}
Stack[top][] = height[i];
Stack[top++][] = cnt;
if(id[sa[i]]!=flag)
sum += tmp;
}
}
return sum;
} char str[MAXN];
int main()
{
int k;
while(scanf("%d",&k)&&k)
{
int len = ;
scanf("%s", str);
int LEN = strlen(str);
for(int j = ; j<LEN; j++)
{
r[len] = str[j];
id[len++] = ;
}
r[len] = '$';
id[len++] = ;
scanf("%s", str);
LEN = strlen(str);
for(int j = ; j<LEN; j++)
{
r[len] = str[j];
id[len++] = ;
}
r[len] = ;
DA(r,sa,Rank,height,len,);
cout<< cal(k,len,)+cal(k,len,) <<endl;
}
}

POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数

    题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...

  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 ...

随机推荐

  1. 选择一个 Python Web 框架:Django vs Flask vs Pyramid

    Pyramid, Django, 和 Flask都是优秀的框架,为项目选择其中的哪一个都是伤脑筋的事.我们将会用三种框架实现相同功能的应用来更容易的对比三者.也可以直接跳到框架实战(Framework ...

  2. PGM图片格式与代码

    这两天在搞神经网络,里面的一个人脸数据库的图片格式是PGM,事实上之前早就知道了这个图片格式,可是没去深究这个图片格式的数据究竟是什么安排的.搜索了下百度百科,发现介绍的真是简单,以下就自己来系统地整 ...

  3. Async Await 使用

    1.简单例子 var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(func ...

  4. 【BIEE】数据透视表格第一列添加序号

    现在有这么一个需求,需要在数据透视图的表格前面条件一列序号,作为行号,如下图: 那么实现这个如何实现呢? 只需要在BIEE分析编辑界面,新建一列,然后公式定义为:RCOUNT(RSUM(1)) ,保存 ...

  5. mapreduce_template

    Hadoop Tutorial - YDN https://developer.yahoo.com/hadoop/tutorial/module4.html import java.io.IOExce ...

  6. Away3D引擎学习笔记(一)资源加载解析块

    前文:Away3D断断续续用了一段时间了,三维相关的很多算法,计算转换还是有点绕,整理些自己觉得还有点意思东西,希望大家有用. 三维开始,Away3D构架你场景那几行代码各处都有,这里就不copy了, ...

  7. condarc文件

    channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/menpo/ - https://mirrors.tuna.tsingh ...

  8. Python结合NC.exe 实现模拟登录&批量填表

    1.工作需求 有很多事项,每个事项分为:名称.种类.时间等,需要把每个事项逐个输入到网页中并提交. 如果用人肉操作的话,流程就是先登录到网站后台,点击“添加”——>输入各项内容——>点击“ ...

  9. Map输出数据的处理类MapOutputBuffer分析

    MapOutputBuffer顾名思义就是Map输出结果的一个Buffer,用户在编写map方法的时候有一个参数OutputCollector: void map(K1 key, V1 value, ...

  10. 华为p20:拍美景,听讲解,旅行更智能

    华为P20轰轰烈烈地上市了,本来对手机并不感冒的我,看到身边的好友换了P20,不禁感慨:这个月的活又要白干了,全部都要上交给华为,因为这款手机完全戳中了旅游爱好者的痛点. 痛点一:丢弃笨重的单反,手机 ...