poj 3415 Common Substrings【SA+单调栈】
把两个串中间加一个未出现字符接起来,然后求SA
然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献
两部分分别作,都用单调栈维护一段里的height最小值(因为lcp是排序后两后缀中间height最小值),然后根据每次入栈种类来给答案算贡献
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500005;
int n,m,k,wa[N],wb[N],wv[N],wsu[N],sa[N],rk[N],he[N],s[N],v[N],top;
long long tot,ans;
char c[N],t[N];
bool cmp(int r[],int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void saa(char r[],int n,int m)
{
int *x=wa,*y=wb;
for(int i=0;i<=m;i++)
wsu[i]=0;
for(int i=1;i<=n;i++)
wsu[x[i]=r[i]]++;
for(int i=1;i<=m;i++)
wsu[i]+=wsu[i-1];
for(int i=n;i>=1;i--)
sa[wsu[x[i]]--]=i;
for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
{
p=0;
for(int i=n-j+1;i<=n;i++)
y[++p]=i;
for(int i=1;i<=n;i++)
if(sa[i]>j)
y[++p]=sa[i]-j;
for(int i=1;i<=n;i++)
wv[i]=x[y[i]];
for(int i=0;i<=m;i++)
wsu[i]=0;
for(int i=1;i<=n;i++)
wsu[wv[i]]++;
for(int i=1;i<=m;i++)
wsu[i]+=wsu[i-1];
for(int i=n;i>=1;i--)
sa[wsu[wv[i]]--]=y[i];
swap(x,y);
p=1;
x[sa[1]]=1;
for(int i=2;i<=n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
}
for(int i=1;i<=n;i++)
rk[sa[i]]=i;
for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
int main()
{
while(scanf("%d",&k)&&k)
{
scanf("%s%s",c+1,t+1);
n=strlen(c+1),m=strlen(t+1);
c[n+1]=1;
for(int i=n+2;i<=n+m+1;i++)
c[i]=t[i-n-1];
saa(c,n+m+1,200);
sa[0]=n+m+2;
// for(int i=0;i<=n+m+2;i++)
// cerr<<sa[i]-1<<" ";
// cerr<<endl;
ans=0,top=0,tot=0;
for(int i=1;i<=n+m+1;i++)
{
if(he[i]<k)
top=0,tot=0;
else
{
int con=0;
if(sa[i-1]<=n)
con++,tot+=he[i]-k+1;
while(top>0&&he[i]<=s[top])
tot-=v[top]*(s[top]-he[i]),con+=v[top--];
s[++top]=he[i],v[top]=con;
if(sa[i]>n+1)
ans+=tot;//cerr<<tot<<endl;
}
}//cerr<<ans<<endl;
top=0,tot=0;
for(int i=1;i<=n+m+1;i++)
{
if(he[i]<k)
top=0,tot=0;
else
{
int con=0;
if(sa[i-1]>n+1)
con++,tot+=he[i]-k+1;
while(top>0&&he[i]<=s[top])
tot-=v[top]*(s[top]-he[i]),con+=v[top--];
s[++top]=he[i],v[top]=con;
if(sa[i]<=n)
ans+=tot;
}
}
printf("%lld\n",ans);
}
return 0;
}
poj 3415 Common Substrings【SA+单调栈】的更多相关文章
- 【POJ3415】 Common Substrings (SA+单调栈)
这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...
- 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 - 后缀数组 - 二分答案 - 单调栈
题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...
- POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)
http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...
- 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 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- 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 ...
随机推荐
- gameplay理解
Camera视角:确定显示的视场及视角. Game:显示的基类.静态单例模式.但是获取方式很奇怪. Game::getInstance得到的是__gameInstance,但是__gameInstan ...
- cs6 mac 破解方法
Photoshop CS6 重点功能: 1.Photoshop CS6 包含Photoshop CS6和Photoshop CS6 Extended中所有功能,快去试一试3D图像编辑和Photosho ...
- Java基础:执行时异常和非执行时异常
1.Java异常机制 Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为全部异常的超类. Java中的异常分为两大类:错误Error和异常Exception.Jav ...
- EasyBCD在windows7基础上安装Ubuntu 14.04双系统详
把下载好的ubuntu安装包放在C盘根文件夹下,利用Daemon Tools 将安装包下casper文件夹的vmlinuz.efi和initrd.lz复制到C盘根文件夹下,紧接着打开easybcd,在 ...
- 距特征之k阶距概念
k阶原点距和k阶中心距各是说明什么数字特征 http://www.cnblogs.com/emanlee/archive/2011/04/25/2028628.html 二阶中心距,也叫作方差,它告诉 ...
- 按行读入xml文件,删除不需要的行 -Java
删除挺麻烦的,这里其实只是把需要的行存到arraylist中再存到另一个文件中 import java.io.BufferedReader;import java.io.BufferedWriter; ...
- POJ1077 Eight —— 经典的搜索问题
题目链接:http://poj.org/problem?id=1077 Eight Time Limit: 1000MS Memory Limit: 65536K Total Submission ...
- java 读写Oracle Blob字段
许久没有分享代码了,把这段时间写的一个Java操作Blob字段,有日子没写Java了,就当作笔记记录一下.1. [代码][Java]代码 跳至 [1] [全屏预览]package com.wa ...
- hdu 1541 Stars 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有 ...
- os、sys和shutil模块
运行环境:python3 OS模块:os 模块提供了一个统一的操作系统的接口函数 下面的path指路径的意思 os.stat(file) #查询文件属性操作 os.sep #取代操作系统特定的路径分隔 ...