poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 11469 | Accepted: 3796 |
Description
A substring of a string T is defined as:
T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|.
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
S = {(i, j, k) | k≥K, A(i, k)=B(j, k)}.
You are to give the value of |S| for specific A, B 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
//论文题,按照规矩先把两个串连起来求出heigh数组,heigh数组分组(大于等于k的一组),然后每遇到一个B串就让他和前面的A串求
//lcp,贡献就是lcp-k+1,然后反过来再求一次每个A和前面的B的,但这是n^2的。我们考虑求某个B与前面的A的lcp时是求这一段中的最小
//的heigh值,这样我们可以用一个递增的栈来存储heigh数组把贡献叠加起来,要入栈的元素小于栈顶时对后面的B的贡献值会减小,并且
//还要保存因为他的入栈而出栈了多少大于等于他的元素以备后面的操作(减小贡献值),每遇到B就更新答案。
//这题还是很难的
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN=;
int sa[MAXN+],he[MAXN+],ra[MAXN+],xx[MAXN+],yy[MAXN+],buc[MAXN+],q[MAXN+][];
char s[MAXN+];
int len,m;
void get_suf()
{
int *x=xx,*y=yy;
for(int i=;i<m;i++) buc[i]=;
for(int i=;i<len;i++) buc[x[i]=s[i]]++;
for(int i=;i<m;i++) buc[i]+=buc[i-];
for(int i=len-;i>=;i--) sa[--buc[x[i]]]=i;
for(int k=;k<=len;k<<=){
int p=;
for(int i=len-;i>=len-k;i--) y[p++]=i;
for(int i=;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=;i<m;i++) buc[i]=;
for(int i=;i<len;i++) buc[x[y[i]]]++;
for(int i=;i<m;i++) buc[i]+=buc[i-];
for(int i=len-;i>=;i--) sa[--buc[x[y[i]]]]=y[i];
swap(x,y);
p=;x[sa[]]=;
for(int i=;i<len;i++){
if(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+k]==y[sa[i]+k])
x[sa[i]]=p-;
else x[sa[i]]=p++;
}
if(p>=len) break;
m=p;
}
for(int i=;i<len;i++) ra[sa[i]]=i;
int k=;
for(int i=;i<len;i++){
if(ra[i]==) { he[]=; continue; }
if(k) k--;
int j=sa[ra[i]-];
while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;
he[ra[i]]=k;
}
}
ll solve(int len1,int k)
{
ll ans=,cnt=,sum=,top=;
for(int i=;i<len;i++){
if(he[i]<k) { top=sum=;continue; }
cnt=;
if(sa[i-]<len1) { cnt++;sum+=he[i]-k+; }
while(top&&he[i]<=q[top][]){
sum-=q[top][]*(q[top][]-he[i]);
cnt+=q[top--][];
}
q[++top][]=cnt;
q[top][]=he[i];
if(sa[i]>len1) ans+=sum;
}
sum=;top=;
for(int i=;i<len;i++){
if(he[i]<k) { top=sum=;continue; }
cnt=;
if(sa[i-]>len1) { cnt++;sum+=he[i]-k+; }
while(top&&he[i]<=q[top][]){
sum-=q[top][]*(q[top][]-he[i]);
cnt+=q[top--][];
}
q[++top][]=cnt;
q[top][]=he[i];
if(sa[i]<len1) ans+=sum;
}
return ans;
}
int main()
{
int k;
while(scanf("%d",&k)&&k){
scanf("%s",s);
int len1=strlen(s);
s[len1]='#';
scanf("%s",s+len1+);
len=strlen(s);
m=;
get_suf();
printf("%lld\n",solve(len1,k));
}
return ;
}
poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数的更多相关文章
- POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)
http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...
- POJ 3415 Common Substrings 【长度不小于 K 的公共子串的个数】
传送门:http://poj.org/problem?id=3415 题意:给定两个串,求长度不小于 k 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...
- POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
题意: 长度不小于 k 的公共子串的个数 分析: 基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于 k 的部分全部加起来. 先将两个字符串连起来,中间 ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数
长度不小于k的公共子串的个数,论文里有题解,卡了一上午,因为sum没开long long!!! 没开long long毁一生again--- 以后应该早看POJ里的Discuss啊QAQ #inclu ...
- POJ 3415 不小于k的公共子串的个数
Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 9248 Accepted: 3071 ...
- poj 2774 后缀数组 两个字符串的最长公共子串
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 31904 Accepted: 12 ...
- POJ - 2774~POJ - 3415 后缀数组求解公共字串问题
POJ - 2774: 题意: 求解A,B串的最长公共字串 (摘自罗穗骞的国家集训队论文): 算法分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长 公共子串等价于求 ...
随机推荐
- 四则运算<C++>
代码: #include<iostream> #define N 30 using namespace std; void main() { cout<<"***** ...
- Answer the questions(回答自己的问题)
第一章: 问题:我们现在学了这个专业,如果想全面去了解,应该还要学习哪些课程? 回答:其实软件工程只是一个比较大的范畴,以后如果要出去工作,我们还要细分,比如说开发安卓,开发游戏,web架构方面等很多 ...
- 对JAVA RMI的认识
RMI的定义 RPC (Remote Procedure Call):远程方法调用,用于一个进程调用另一个进程中的过程,从而提供了过程的分布能力. RMI(Remote Method Invocati ...
- HighCharts点击柱形或饼块等加URL或Click事件
我们在做图表的时候,有时候需要在单个数据上加链接或点击事件,是在plotOptions里的events里设置的: 如下代码: plotOptions: { pie: { cursor: 'pointe ...
- 关于Jquery使用中遇到典型问题集锦
①$.post("url",{search:1},function(){},"json")请求数据成功就是不执行回调函数? 答:最大可能导致原因为 数据格式不正 ...
- gitlab修改root密码
在root用户下,执行 [root@localhost gitlab]# sudo gitlab-rails console production -------------------------- ...
- [51CTO]给您介绍Windows10各大版本之间区别
给您介绍Windows10各大版本之间区别 随着win10的不断普及和推广,越来越多的朋友想安装win10系统了,但是很多朋友不知道win10哪个版本好用,为了让大家能够更好的选择win10系统版本, ...
- object & over-write
object & over-write
- python自动化之word文档
#########################docx文件############################ ''' .docx文件有很多结构,有3种不同的类型来表示 在最高一层,Docum ...
- Spring(2):Spring Ioc
1.下载spring-framework-3.2.0 完整包下载路径: https://repo.spring.io/webapp/#/artifacts/browse/tree/Properties ...