字符串(后缀数组):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 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...
随机推荐
- html获取gps坐标
<script> function getLocation(){ var options={ enableHighAccuracy:true, maximumAge:1000 } if(n ...
- 绝对炫的幻灯片插件-SKITTER
绝对炫的幻灯片插件-SKITTER 所属分类:媒体-幻灯片和轮播图,图片展示,滑块和旋转 Includes code source // Styles <link href="css/ ...
- 关于git status
如果只在本地修改,还没有commit,那么用git status, 打印信息为: 如果我本地没有修改文件,就是:
- 关于mssql数据库锁和事务隔离级别
事务隔离级别有4种,这4种级别只是对于读操作,也就是select有不同程度的支持, 读未提交:不会对事务里读出来的数据附加任何锁 读已提交:会对事务里读出来的数据附加共享锁,读完就释放共享锁,其他事务 ...
- java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String
http://blog.csdn.net/agileclipse/article/details/17161225 详情请点击链接查看
- Linux 添加epel源
1.epel-release yum install epel-release 这样有些没办法通过yum 安装 可以这样安装(例如redis)
- 【模板】【网络流】Dinic
/* 唐代杜荀鹤 <小松> 自小刺头深草里,而今渐觉出蓬蒿. 时人不识凌云木,直待凌云始道高. */ #include <iostream> #include <cstd ...
- 深入Java虚拟机读书笔记第五章Java虚拟机
Java虚拟机 Java虚拟机之所以被称之为是虚拟的,就是因为它仅仅是由一个规范来定义的抽象计算机.因此,要运行某个Java程序,首先需要一个符合该规范的具体实现. Java虚拟机的生命周期 一个运行 ...
- AspNet MVC : 操作/控制器过滤器(action filter)
1.Action Filter Action Filter提供了在执行action/controller前后对请求/响应修改的能力,可以应用于action和控制器上,作用在控制器上将自动被应用到该控制 ...
- jquery.lazyload.js图片延迟加载
转:http://www.jb51.net/article/50273.htm 这篇文章主要介绍了Jquery图片延迟加载插件jquery.lazyload.js的使用方法,需要的朋友可以参考下 ...