Common Substrings
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 10002   Accepted: 3302

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
/** POJ 3415 Common Substrings* 给出两个字符串A,B,求长度不小于k的公共子串的个数** 将B接到A的后面,中间用一个没出现的字符隔开,然后求sa和height数组* 然后按height分组,我们只考虑height[i]>=k的后缀,因为小于不符合题意,然后对于每个分组,统计答案* 很容易想到算法就是对于同一组里面的B后缀,我和前面的所有A的后缀比较,累加答案,再反过来对A做一遍即可* 这样的时间复杂度是O(n*n)的,会TLE* 考虑这样的一个性质,后缀i和j的lcp是height[rank[i+1]]...height[rank[j]]的最小值,那么对于* height[i]==s&&sa[i]是B的后缀,它和前面A的答案肯定是最小的height的累加,于是这样我们可以用一个* 单调栈来维护,每当新加入的height小于栈顶的元素,我们就把栈顶元素弹出来,把新的值压入栈中* 怎么统计答案呢?可以先加后减,当计算B的个数时,遇到A的后缀我们就直接累加到答案中,如果和栈顶元素冲突了* 说明多加了一部分,在弹出元素时减去即可,这样多维护一个个数就行了。*/#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;const int MAXN = 200000+100;int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];
void build_sa(int s[],int n,int m)
{int i,j,p,*x=t1,*y=t2;for(i=0;i<m;i++)c[i]=0;for(i=0;i<n;i++)c[x[i]=s[i]]++;for(i=1;i<m;i++)c[i]+=c[i-1];for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;for(j=1;j<=n;j<<=1){p=0;for(i=n-j;i<n;i++)y[p++]=i;for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;for(i=0;i<m;i++)c[i]=0;for(i=0;i<n;i++)c[x[y[i]]]++;for(i=1;i<m;i++)c[i]+=c[i-1];for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];swap(x,y);p=1;x[sa[0]]=0;for(i=1;i<n;i++)x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;if(p>=n)break;m=p;}
}
void getHeight(int s[],int n)
{int i,j,k=0;for(i=0;i<=n;i++) Rank[sa[i]]=i;for(i=0;i<n;i++){if(k)k--;j=sa[Rank[i]-1];while(s[i+k]==s[j+k])k++;height[Rank[i]]=k;}
}
char str1[MAXN],str2[MAXN];
int ss[MAXN];
int sta[MAXN],stb[MAXN];int main()
{int k;while(scanf("%d",&k)==1&&k){scanf("%s",str1);scanf("%s",str2);int len1=strlen(str1);int len2=strlen(str2);int n=len1+len2+1;for(int i=0;i<len1;i++) ss[i]=str1[i];ss[len1]=1;for(int i=0;i<len2;i++) ss[len1+i+1]=str2[i];ss[n]=0;build_sa(ss,n+1,128);getHeight(ss,n);long long ans=0;long long res=0;int top=0;for(int i=2;i<=n;i++){if(height[i]<k){res=0;top=0;continue;}int cnt=0;if(sa[i-1]<len1){cnt++;res+=height[i]-k+1;}while(top>0&&height[i]<=sta[top-1]){top--;res-=stb[top]*(sta[top]-height[i]);cnt+=stb[top];}sta[top]=height[i],stb[top++]=cnt;if(sa[i]>len1) ans+=res;}res=0,top=0;for(int i=2;i<=n;i++){if(height[i]<k){res=0;top=0;continue;}int cnt=0;if(sa[i-1]>len1){cnt++;res+=height[i]-k+1;}while(top>0&&height[i]<=sta[top-1]){top--;res-=stb[top]*(sta[top]-height[i]);cnt+=stb[top];}sta[top]=height[i],stb[top++]=cnt;if(sa[i]<len1) ans+=res;}printf("%lld\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/wangdongkai/p/5785559.html

POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)相关推荐

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

    Common Substrings 后缀数组+单调栈 题解1 题解2 题解3 #include<cstdio> #include<cstring> #include<io ...

  2. POJ 3415 Common Substrings

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

  3. POJ - 3415 Common Substrings(后缀数组+单调栈)

    题目链接:点击查看 题目大意:给出两个字符串,再给出一个k,问两个字符串中长度大于等于k的公共子串有多少个(种类可重复) 题目分析:因为涉及到了子串问题,先用后缀数组跑出height数组来,接下来如果 ...

  4. java 字符串子串_java实现字符串匹配求两个字符串的最大公共子串

    本文实例讲述了java实现求两个字符串最大公共子串的方法.分享给大家供大家参考,具体如下: 最近在项目工作中有一个关于文本对比的需求,经过这段时间的学习,总结了这篇博客内容:求两个字符串的最大公共子串 ...

  5. cdoj915-方老师的分身 II (长度不小于k的最短路)【spfa】

    http://acm.uestc.edu.cn/#/problem/show/915 方老师的分身 II Time Limit: 10000/5000MS (Java/Others)     Memo ...

  6. 【POJ3415】 Common Substrings (SA+单调栈)

    这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...

  7. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  8. POJ 3415 后缀数组+单调栈

    题目大意: 给定A,B两种字符串,问他们当中的长度大于k的公共子串的个数有多少个 这道题目本身理解不难,将两个字符串合并后求出它的后缀数组 然后利用后缀数组求解答案 这里一开始看题解说要用栈的思想,觉 ...

  9. Algorithm:C++/python语言实现之求旋转数组最小值、求零子数组、求最长公共子序列和最长公共子串、求LCS与字符串编辑距离

    Algorithm:C++/python语言实现之求旋转数组最小值.求零子数组.求最长公共子序列和最长公共子串.求LCS与字符串编辑距离 目录 一.求旋转数组最小值 1.分析问题 2.解决思路 二.求 ...

  10. 最长公共子串LCS (Longest Common Subsequence) 算法

    三个方法都有所借鉴,但代码部分是自己试着写出来的,虽然最后的运行结果都是正确的,但此过程中难免会有考虑不周全的地方,如发现代码某些地方有误,欢迎指正.同时有新的想法,也可以提出! 采用顺序结构存储串, ...

最新文章

  1. Arduino(新手之路2)
  2. Python算法和数据结构:在二叉树中找到和为sum的所有路径
  3. Windows下Tomcat服务器的安装和配置
  4. 使用 yolov3训练 voc2012
  5. V神最新演讲:以太坊2.0的分片交易
  6. 打印系统里所有Category为03的IBASE及其关联的object ID
  7. 【Python配置】Win10配置Python3、Numpy、PyCharm、Anaconda
  8. Oracle数据同步接口中,对于NUMBER、DATE类型数据,从resultSet中直接获取造成精度丢失的解决方案
  9. paip.提升效率---filter map reduce 的java 函数式编程实现
  10. 电脑小手图标怎么去除_取消共享文件夹图标上的小手
  11. arduino系列教程之触摸开关(外部中断)开关小灯led
  12. 乐高大颗粒作品之西游记
  13. Eclipse+WIN7+CC2538移植开发Contiki
  14. java微服务Nacos配置管理
  15. kubernetes dev client-go 输出资源
  16. 安装Debian系统
  17. Android开发交流群
  18. 大学毕业小总结以及感想
  19. 计算机人文素养教案,谈谈信息技术课堂中人文素养培养的感想和体会
  20. SpringBoot集成支付平台

热门文章

  1. openmv探索_5_openmv读取的数据输出到外界
  2. CUDA 和 GPU
  3. 李航:做本质的、严谨的、有意思的研究,纪念我的导师长尾真教授
  4. 比赛 | 第一届古汉语分词与词性标注国际评测来啦
  5. 拿到参考资料的预训练模型,太可怕了!
  6. 本周论文推荐(12.14-12.20)
  7. 深度学习2.0-37.循环神经网络层
  8. Python中的特殊方法、属性和迭代器
  9. 猫工智能:卷积神经网络层的实现
  10. 初识视觉SLAM:用相机解决定位和建图问题