字符串(后缀数组):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 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
这道题呃,有些考验程序实践能力。
题意:对于给定的两个字符串和一个整数K,求两个字符串长度大于等于K的公共子串数目。
将两个字符串接起来,中间用一个特殊字符隔开,枚举Lcp,暴力枚举是O(n³)的,死活都不可能过。
这是我们想:能否使用以前枚举的信息?所以正解就出来了:单调栈优化!
具体咋打就看代码吧~~~
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- using namespace std;
- const int maxn=;
- char S[maxn];
- int sa[maxn],r[maxn],rank[maxn],lcp[maxn];
- int Wv[maxn],Ws[maxn],Wa[maxn],Wb[maxn],len;
- bool cmp(int *p,int a,int b,int l){
- return p[a]==p[b]&&p[a+l]==p[b+l];
- }
- void DA(int n,int m){
- int i,j,p,*x=Wa,*y=Wb,*t;
- for(i=;i<m;i++)Ws[i]=;
- for(i=;i<n;i++)++Ws[x[i]=r[i]];
- for(i=;i<m;i++)Ws[i]+=Ws[i-];
- for(i=n-;i>=;i--)sa[--Ws[x[i]]]=i;
- for(j=,p=;p<n;m=p,j<<=){
- for(p=,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++)Ws[i]=;
- for(i=;i<n;i++)++Ws[Wv[i]=x[y[i]]];
- for(i=;i<m;i++)Ws[i]+=Ws[i-];
- for(i=n-;i>=;i--)
- sa[--Ws[Wv[i]]]=y[i];
- for(t=x,x=y,y=t,i=,p=,x[sa[]]=;i<n;i++)
- x[sa[i]]=cmp(y,sa[i],sa[i-],j)?p-:p++;
- }
- }
- void Lcp(int n){
- int i,j,k=;
- for(i=;i<=n;i++)rank[sa[i]]=i;
- for(i=;i<n;lcp[rank[i++]]=k)
- for(k?--k:k,j=sa[rank[i]-];r[i+k]==r[j+k];++k);
- }
- int s[maxn][];
- int main(){
- int n,k;
- while(~scanf("%d",&k)&&k){
- scanf("%s",S);
- n=strlen(S);S[n]='%';
- scanf("%s",S+n+);
- len=strlen(S);
- for(int i=;i<len;i++)
- r[i]=S[i];
- r[len]=;
- DA(len+,);
- Lcp(len);
- int cnt=;
- long long ans=,sum=;
- for(int i=;i<=len;i++){
- if(lcp[i]<k){
- sum=;cnt=;
- continue;
- }
- int tot=;
- if(sa[i-]>n){
- sum+=lcp[i]-k+;
- tot++;
- }
- while(cnt&&s[cnt][]>=lcp[i]){
- tot+=s[cnt][];
- sum-=1ll*s[cnt][]*(s[cnt][]-lcp[i]);
- cnt--;
- }
- s[++cnt][]=lcp[i];
- s[cnt][]=tot;
- if(sa[i]<n)ans+=sum;
- }
- cnt=;sum=;
- for(int i=;i<=len;i++){
- if(lcp[i]<k){
- sum=;cnt=;
- continue;
- }
- int tot=;
- if(sa[i-]<n){
- sum+=lcp[i]-k+;
- tot++;
- }
- while(cnt&&s[cnt][]>=lcp[i]){
- tot+=s[cnt][];
- sum-=1ll*s[cnt][]*(s[cnt][]-lcp[i]);
- cnt--;
- }
- s[++cnt][]=lcp[i];
- s[cnt][]=tot;
- if(sa[i]>n)ans+=sum;
- }
- printf("%lld\n",ans);
- }
- return ;
- }
字符串(后缀数组):POJ 3415 Common Substrings的更多相关文章
- POJ 3415 Common Substrings(后缀数组 + 单调栈)题解
题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...
- poj 3415 Common Substrings(后缀数组+单调栈)
http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Sub ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- 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 (后缀数组)
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 s ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- poj 3415 Common Substrings
题目链接:http://poj.org/problem?id=3415 题目分类:后缀数组 题意:给出两个串和一个数字k,求两个串的公共字串大于等于k的数目 代码: //#include<bit ...
- POJ 3415 Common Substrings 【长度不小于 K 的公共子串的个数】
传送门:http://poj.org/problem?id=3415 题意:给定两个串,求长度不小于 k 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...
随机推荐
- python版本简历
- selenium+eclipse+python环境
1.下载并安装jdk,配置环境变量: 2.下载并安装python,配置path系统环境变量:D:\Program Files\python34: 3.安装selenium,在安装好的python路径D ...
- 测测你适合从事Web前端开发吗
一般初创的互联网公司最烧钱的时候往往都是刚刚获得风投或融资的时候,因为他们要把钱砸向前端,因为那时候没有客户访问,对于企业来说只有先做好前端技 术.做好客户体验一切才有可能.用户体验做好,才有人访问, ...
- c# 关于dispose
只有针对非托管资源才需要调用dispose,包含托管资源包装了非托管资源这样的情况.也只有非托管资源调用dispose才会立即进行资源清理,托管资源即使调用dispose也还是交由gc自动完成,并非立 ...
- 导入sql时报日期类型错误
导入的脚本中有的日期类型数据是:0000-00-00 00:..这种格式的. 需要把这种格式修改一下.有的mysql版本不支持这种0000.设置成当前时间即可
- 打造属于前端的Uri解析器
今天和大家一起讨论一下如何打造一个属于前端的url参数解析器.如果你是一个Web开发工程师,如果你了解过后端开发语言,譬如:PHP,Java等,那么你对下面的代码应该不会陌生: $kw = $_GET ...
- Deep Learning 学习随记(五)深度网络--续
前面记到了深度网络这一章.当时觉得练习应该挺简单的,用不了多少时间,结果训练时间真够长的...途中debug的时候还手贱的clear了一下,又得从头开始运行.不过最终还是调试成功了,sigh~ 前一篇 ...
- Xcode4.4中,代码无法高亮、无法自动补全
1.代码无法高亮显示:2.代码不能自动补全,或者给出提示建议:(当然这个补全的功能我在设置当中是打开的状态)3.新建一个项目,代码还是依然没有高亮显示,但是有补全功能:4.然后我就在网络上搜索了相关的 ...
- C# List
命名空间:using System.Collections; class Program {//做个比较 static void Main(string[] args) { //new对象 Cls a ...
- css清除浮动方法大全
清除浮动这个问题,做前端的应该再熟悉不过了,也是每一个web前台设计师 必须掌握的机能. 为什么浮动这么难? 因为浮动会使当前标签产生向上浮的效果,同时会影响到前后标签.父级标签的位置及 width ...