POJ 3415 Common Substrings ——后缀数组
【题目分析】
判断有多少个长度不小于k的相同子串的数目。
N^2显然是可以做到的。
其实可以维护一个关于height的单调栈,统计一下贡献,就可以了。
其实还是挺难写的OTZ。
【代码】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 300005
#define LL long long
#define inf 0x3f3f3f3f
#define F(i,j,k) for (LL i=j;i<=k;++i)
#define D(i,j,k) for (LL i=j;i>=k;--i)
void Finout()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("wa.txt","w",stdout);
#endif
}
LL Getint()
{
LL x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
char ss[maxn];
LL n,l1,l2,k;
struct SuffixArray{
LL s[maxn];
LL rk[maxn],h[maxn],cnt[maxn],tmp[maxn],sa[maxn];
void init()
{
memset(s,0,sizeof s);
// memset(rk,0,sizeof rk);
// memset(h,0,sizeof h);
// memset(cnt,0,sizeof cnt);
// memset(tmp,0,sizeof tmp);
// memset(sa,0,sizeof sa);
}
void build(LL n,LL m)
{
LL i,j,k; n++;
F(i,0,2*n+5) rk[i]=h[i]=tmp[i]=sa[i]=0;
F(i,0,m-1) cnt[i]=0;
F(i,0,n-1) cnt[rk[i]=s[i]]++;
F(i,1,m-1) cnt[i]+=cnt[i-1];
F(i,0,n-1) sa[--cnt[rk[i]]]=i;
for (k=1;k<=n;k<<=1)
{
F(i,0,n-1)
{
j=sa[i]-k;
if (j<0) j+=n;
tmp[cnt[rk[j]]++]=j;
}
sa[tmp[cnt[0]=0]]=j=0;
F(i,1,n-1)
{
if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rk,sa,n*sizeof(LL));
memcpy(sa,tmp,n*sizeof(LL));
if (j>=n-1) break;
}
for (j=rk[h[i=k=0]=0];i<n-1;++i,++k)
while (~k&&s[i]!=s[sa[j-1]+k]) h[j]=k--,j=rk[sa[j]+1];
//Debug
/*
F(i,0,n-1) cout<<s[i]<<" "; cout<<endl;
F(i,0,n-1) cout<<sa[i]<<" ";cout<<endl;
F(i,0,n-1) cout<<h[i]<<" ";cout<<endl;
*/
//Debug over
}
LL sta[maxn][2],top;
LL tot,sum;
void solve(LL n,LL k)
{
// n++;
top=0;sum=0;tot=0;
F(i,1,n)
{
if (h[i]<k) top=tot=0;
else
{
LL cnt=0;
if (sa[i-1]<l1) cnt++,tot+=h[i]-k+1;
while (top>0&&h[i]<=sta[top-1][0])
{
top--;
tot-=sta[top][1]*(sta[top][0]-h[i]);
cnt+=sta[top][1];
}
sta[top][0]=h[i]; sta[top++][1]=cnt;
if (sa[i]>l1) sum+=tot;
}
}
top=tot=0;
F(i,1,n)
{
if (h[i]<k) top=tot=0;
else
{
LL cnt=0;
if (sa[i-1]>l1) cnt++,tot+=h[i]-k+1;
while (top>0&&h[i]<=sta[top-1][0])
{
top--;
tot-=sta[top][1]*(sta[top][0]-h[i]);
cnt+=sta[top][1];
}
sta[top][0]=h[i]; sta[top++][1]=cnt;
if (sa[i]<l1) sum+=tot;
}
}
cout<<sum<<endl;
}
}arr;
int main()
{
Finout();
while (scanf("%lld",&k)!=EOF&&k)
{
arr.init();
memset(ss,0,sizeof ss);
scanf("%s",ss);l1=strlen(ss);//cout<<l1<<endl;
F(i,0,l1-1) arr.s[i]=ss[i];
arr.s[l1]=248;
memset(ss,0,sizeof ss);
scanf("%s",ss);l2=strlen(ss);//cout<<l2<<endl;
F(i,0,l2-1) arr.s[l1+i+1]=ss[i];
arr.build(l1+l2+1,250);
arr.solve(l1+l2+1,k);
}
}
POJ 3415 Common Substrings ——后缀数组的更多相关文章
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- 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 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈
题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...
- POJ.3145.Common Substrings(后缀数组 倍增 单调栈)
题目链接 \(Description\) 求两个字符串长度不小于k的公共子串对数. \(Solution\) 求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}( ...
- POJ 3415 Common Substrings(后缀数组 + 单调栈)题解
题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...
随机推荐
- D3.js学习(二)
上一节中我们已经画出了一个基本的图表,不过忘了给坐标轴添加标签了,所以在本节中我们要给坐标轴加上标签,目标效果如下 给X轴添加标签 很明显,标签是不是一个text内容块啊,所以我们只要在svg中添加一 ...
- FFmpeg和X264的交叉编译环境
在下载好了FFmpeg和X264的源码包之后,在Linux下进行安装的基本流程就是切换到其源码的根目录,然后以此执行以下命令.基本上所有的开源源码包的默认编译安装都是这三步. ./configure ...
- jQuery插件中的this指的是什么
在jQuery插件的范围里, this关键字代表了这个插件将要执行的jQuery对象, 但是在其他包含callback的jQuery函数中,this关键字代表了原生的DOM元素.这常常会导致开发者误将 ...
- This is US 我们的生活
温情暖心剧 看点在于真实,能让人找到不少共鸣像极了平淡而操蛋的生活,不断交织着苦涩和甘甜,柴米油盐.酸甜苦辣.嬉笑打闹.悲欢离合.温情又不尽如人意 this is us,our life 生活有如柠檬 ...
- CSS & JS 制作滚动幻灯片
==================纯CSS方式==================== <!DOCTYPE html> <html> <head> <met ...
- Python 网络爬虫(新闻采集脚本)
=====================爬虫原理===================== 通过Python访问新闻首页,获取首页所有新闻链接,并存放至URL集合中. 逐一取出集合中的URL,并访问 ...
- MySQL · 答疑解惑 · MySQL 锁问题最佳实践
http://mysql.taobao.org/monthly/2016/03/10/ 前言 最近一段时间处理了较多锁的问题,包括锁等待导致业务连接堆积或超时,死锁导致业务失败等,这类问题对业务可能会 ...
- MyBatis:统计数量
dao: /** * 统计商家的案例数量 * * @param shopId * @return */ long countByShopId(Long shopId); @Override publi ...
- 出售Illustrator脚本插件面板(包含面板源码,以及面板上所有的功能源码)
出售Illustrator脚本插件面板(包含面板源码,以及面板上所有的功能源码) 购买后可提供相应的小修改,以及教你使用往这个多列面里再加上按钮功能! 这套源码可作为工作使用,也可用为新手学习AI脚面 ...
- CodeForces 589J Cleaner Robot
题目链接 题意:一个机器人打扫卫生,URDL代表初始时机器人面对的方向上右下左. ' . ' 代表可以打扫的, ' * ' 代表家具,如果机器人遇到家具就顺时针转90度,问机器人能打扫多少面积. 题解 ...