字符串(后缀数组):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 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...
随机推荐
- DataTable用法
在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结. 一.DataTable简 ...
- date和long的相互转换
import java.text.SimpleDateFormat; import java.util.Date; public class T { public static void main(S ...
- webGIS(离线版)研究路线归总
特注:不做详解,说明网上资源很多,找一篇,照着走一遍即可. 1.数据源要满足开源.Free且地理信息要完善 几经周折,选择了OSM,具体信息可以去其官方查看(它竟然把中国一分为二,大陆.台湾,坑爹!! ...
- 2017JAVA必读书籍
1.深入理解Java虚拟机:JVM高级特性与最佳实践 2.Oracle查询优化改写技巧与案例 3.Effective Java 4.Spring3.x企业应用开发实战 5.Spring技术内幕:深入解 ...
- JavaScript 字符串(String) 对象
JavaScript 字符串(String) 对象 String 对象用于处理已有的字符块. JavaScript 字符串 一个字符串用于存储一系列字符就像 "John Doe". ...
- HTML页面中启用360浏览器极速模式
今天做页面突然遇到浏览器一直在兼容模式下运行,体验不好,通过查询文档,在<head>中加入<meta name="renderer" content=" ...
- SGU 113.Nearly prime numbers
水一个代码: #include <iostream> using namespace std; int n, a; bool ok; bool prime (int x) { ; i * ...
- access_token的获取方式
获取Access Token $appid = ""; $appsecret = ""; $url = "https://api.weixin.q ...
- php基础知识【函数】(3)字符串string
一.大小写转换 1.strtolower()--转换为小写. echo strtolower("Hello WORLD!"); //hello world! 2.strtouppe ...
- PHP_EOL常量
PHP_EOL 换行符 unix系列用 \n windows系列用 \r\n mac用 \r PHP中可以用PHP_EOL来替代,以提高代码的源代码级可移植性 如: <?php echo PHP ...