题目链接

\(Description\)

求两个字符串长度不小于k的公共子串对数。

\(Solution\)

求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}(A'到B'ht[]的最小值)。

维护一个栈,栈中ht从底到顶递减。

如果当前是求B中后缀i和前边A中子串的答案,那么记录之前的∑(ht(A)),这就是前边A对i的贡献。

然后更新这个栈,若ht[i]>ht[top],入栈即可 但不对B计算答案;

若ht[i]<=ht[top],因为公共子串是min{ht()},i入栈后要对所有ht[top-1]>=ht[i]的top-1改成ht[i],并且i出栈(期间减去当前多算的答案ht[top]-ht[top-1]),直到ht[top-1]<ht[top]

//6096K	704MS
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
const int N=2e5+10; int n,sa[N],ht[N],rk[N],sa2[N],tm[N],sk[N],val[N],bel[N];
char s[N]; void Get_SA()
{
int *x=rk,*y=sa2,m=260;
for(int i=0; i<=m; ++i) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]+1];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[i]]--]=i;
for(int p=0,k=1; k<n; k<<=1,m=p,p=0)
{
for(int i=n-k+1; i<=n; ++i) y[++p]=i;
for(int i=1; i<=n; ++i) if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=0; i<=m; ++i) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i]; std::swap(x,y), p=x[sa[1]]=1;
for(int i=2; i<=n; ++i)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
if(p>=n) break;
}
for(int i=1; i<=n; ++i) rk[sa[i]]=i;
ht[1]=0;
for(int k=0,p,i=1; i<=n; ++i)
{
if(rk[i]==1) continue;
if(k) --k;
p=sa[rk[i]-1];
while(i+k<=n&&p+k<=n&&s[i+k]==s[p+k]) ++k;
ht[rk[i]]=k;
}
} int main()
{
int k;
while(scanf("%d",&k),k)
{
scanf("%s",s+1); int l=strlen(s+1);
s[l+1]=1, scanf("%s",s+2+l), n=strlen(s+1);
Get_SA();
for(int i=2/*1*/; i<=n; ++i)
{
ht[i]-=k-1, bel[i]=sa[i]>l;
if(ht[i]<0) ht[i]=0;
}
LL res=0,tmp;
val[0]=-1;
for(int top,t=0; t<=1; ++t)
{
tmp=0, top=0;
for(int i=2/*1*/; i<=n; ++i)//ht[1]就是补充字符 计算不计算都行
{
if(bel[i]!=t) res+=tmp;
sk[++top]=bel[i]==t;
val[top]=ht[i+1];
tmp+=(LL)sk[top]*val[top];
while(val[top-1]>=val[top])
{
--top;
tmp-=(LL)(val[top]-val[top+1])*sk[top];//减去之前多余的贡献
val[top]=val[top+1], sk[top]+=sk[top+1];
}
}
}
printf("%lld\n",res);
}
return 0;
}

POJ.3145.Common Substrings(后缀数组 倍增 单调栈)的更多相关文章

  1. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  2. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  3. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  4. 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 ...

  5. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  6. POJ 3415 Common Substrings 后缀数组+并查集

    后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height   求完之后按height值从大往小合并.  height值代表的是  sa[i]和sa[i ...

  7. 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 ...

  8. POJ 3415 Common Substrings ——后缀数组

    [题目分析] 判断有多少个长度不小于k的相同子串的数目. N^2显然是可以做到的. 其实可以维护一个关于height的单调栈,统计一下贡献,就可以了. 其实还是挺难写的OTZ. [代码] #inclu ...

  9. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

随机推荐

  1. 【逆向工具】IDA使用6-签名文件制作

    0x1 签名文件制作的方法: 找到静态编译的程序库 使用IDA中的fair工具包,对静态库操作,生成特征库(IDA6.8 是flair68.zip) 0x2 步骤 第一步:使用pcf生成对应静态库的p ...

  2. 【转】PyDev Eclipse使用技巧说明

    PyDev Package Explorer 创建项目 在开展工作之前,需要创建一个新的项目.在 Eclipse 菜单栏中,选择 File > New > Project > Pyd ...

  3. 那些IT行业的经典定律

    几十年来,IT界有一些非常著名的定律,蕴含着行业发展的大智慧,非常有趣,略作收集总结,再加上一丁点自己的浅见~ 一.摩尔定律:价格不变,集成电路上可容纳的元器件数目,约每隔18个月便会翻一倍,性能也将 ...

  4. V4L2应用程序框架【转】

    转自:https://www.cnblogs.com/hzhida/archive/2012/05/29/2524397.html V4L2是V4L的升级版本,linux下视频设备程序提供了一套接口规 ...

  5. 默认以管理员身份运行VS2013/15/17

    方法如下: 1.右击VS的快捷方式,选择[属性],打开属性对话框,再点击[高级]按钮,如下图所示: 2.再勾选[用管理员身份运行],点击[确定]即可: 然后就可以双击VS快捷方式,直接以管理员身份运行 ...

  6. eclipse自动添加注释

    自动添加注释 快捷键:alt shift jwindows-->preference Java-->Code Style-->Code Templates code-->new ...

  7. centos6.5下java和tomcat环境部署

    软件包: tomcat安装包 apache-tomcat-7.0.67.zip jdk安装包 jdk-6u10-linux-x64.bin 下载地址:http://www.oracle.com/tec ...

  8. 关卡得分(if 嵌套for)与(for嵌套if)

  9. 前景检测(1):VIBE

    参考:http://blog.csdn.net/zouxy09/article/details/9622285 看论文很多细节不明白,看这位博主实现的代码就能明白了.

  10. vue+element之多表单验证

    方法一:利用promise var p1=new Promise(function(resolve, reject) { this.$refs[form1].validate((valid) => ...