POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 10002 | Accepted: 3302 |
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
/** 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的公共子串的个数)相关推荐
- POJ - 3415 Common Substrings(长度不小于K的公共子串个数)
Common Substrings 后缀数组+单调栈 题解1 题解2 题解3 #include<cstdio> #include<cstring> #include<io ...
- 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 ...
- POJ - 3415 Common Substrings(后缀数组+单调栈)
题目链接:点击查看 题目大意:给出两个字符串,再给出一个k,问两个字符串中长度大于等于k的公共子串有多少个(种类可重复) 题目分析:因为涉及到了子串问题,先用后缀数组跑出height数组来,接下来如果 ...
- java 字符串子串_java实现字符串匹配求两个字符串的最大公共子串
本文实例讲述了java实现求两个字符串最大公共子串的方法.分享给大家供大家参考,具体如下: 最近在项目工作中有一个关于文本对比的需求,经过这段时间的学习,总结了这篇博客内容:求两个字符串的最大公共子串 ...
- cdoj915-方老师的分身 II (长度不小于k的最短路)【spfa】
http://acm.uestc.edu.cn/#/problem/show/915 方老师的分身 II Time Limit: 10000/5000MS (Java/Others) Memo ...
- 【POJ3415】 Common Substrings (SA+单调栈)
这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...
- 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数
目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...
- POJ 3415 后缀数组+单调栈
题目大意: 给定A,B两种字符串,问他们当中的长度大于k的公共子串的个数有多少个 这道题目本身理解不难,将两个字符串合并后求出它的后缀数组 然后利用后缀数组求解答案 这里一开始看题解说要用栈的思想,觉 ...
- Algorithm:C++/python语言实现之求旋转数组最小值、求零子数组、求最长公共子序列和最长公共子串、求LCS与字符串编辑距离
Algorithm:C++/python语言实现之求旋转数组最小值.求零子数组.求最长公共子序列和最长公共子串.求LCS与字符串编辑距离 目录 一.求旋转数组最小值 1.分析问题 2.解决思路 二.求 ...
- 最长公共子串LCS (Longest Common Subsequence) 算法
三个方法都有所借鉴,但代码部分是自己试着写出来的,虽然最后的运行结果都是正确的,但此过程中难免会有考虑不周全的地方,如发现代码某些地方有误,欢迎指正.同时有新的想法,也可以提出! 采用顺序结构存储串, ...
最新文章
- Arduino(新手之路2)
- Python算法和数据结构:在二叉树中找到和为sum的所有路径
- Windows下Tomcat服务器的安装和配置
- 使用 yolov3训练 voc2012
- V神最新演讲:以太坊2.0的分片交易
- 打印系统里所有Category为03的IBASE及其关联的object ID
- 【Python配置】Win10配置Python3、Numpy、PyCharm、Anaconda
- Oracle数据同步接口中,对于NUMBER、DATE类型数据,从resultSet中直接获取造成精度丢失的解决方案
- paip.提升效率---filter map reduce 的java 函数式编程实现
- 电脑小手图标怎么去除_取消共享文件夹图标上的小手
- arduino系列教程之触摸开关(外部中断)开关小灯led
- 乐高大颗粒作品之西游记
- Eclipse+WIN7+CC2538移植开发Contiki
- java微服务Nacos配置管理
- kubernetes dev client-go 输出资源
- 安装Debian系统
- Android开发交流群
- 大学毕业小总结以及感想
- 计算机人文素养教案,谈谈信息技术课堂中人文素养培养的感想和体会
- SpringBoot集成支付平台