题目:http://poj.org/problem?id=3415

先用后缀数组处理出 ht[i];

用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前后缀的LCP,其中长度 >= K 的加到答案;

因为单调栈中是一段一段阶梯状的,只存了一段端点的位置,所以再记录一个 cnt 表示这一段的长度,算贡献时乘上 cnt;

因为是两个串之间,所以先统计 B 在 A 排名前的答案,再重复一遍统计 A 在 B 排名前的答案;

但是 ht[i] 是 sa[i] 和 sa[i-1] 的LCP,所以 ht[i] 是否计入贡献应该考虑 i-1 位置...突然变得很麻烦,不太会弄了...

于是参考了一下TJ(囧),原来就是判断一下 i-1 是否要被统计,如果要统计 B 而 i-1 是 B 中的,就把 ht[i] 也累加到 sum 中;

还有一个很好的操作是如果 ht[i] < K,那么取 min 显然都会取成 < K 的,没贡献了,所以直接 sum=0 , top = 0,就省去了 max(0,ht[i]-K+1) 的分类麻烦。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=1e5+,xxn=(xn<<);//xxn
int n,m,tax[xxn],sa[xxn],rk[xxn],tp[xxn],ht[xxn],sta[xxn],top,cnt[xxn];
char a[xn],b[xn],s[xxn];
void Rsort()
{
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[rk[tp[i]]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
}
void work()
{
for(int i=;i<=n;i++)rk[i]=s[i],tp[i]=i;
Rsort();
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;i++)tp[++num]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++num]=sa[i]-k;
Rsort();
memcpy(tp,rk,sizeof rk);//swap(rk,tp);
rk[sa[]]=; num=;
for(int i=;i<=n;i++)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[sa[i]+k]==tp[sa[i-]+k])?num:++num;
if(num==n)break;
m=num;
}
}
void get()
{
int k=; ht[]=;
for(int i=;i<=n;i++)
{
if(rk[i]==)continue;
if(k)k--; int j=sa[rk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
ht[rk[i]]=k;
}
}
int main()
{
int K;
while()
{
scanf("%d",&K); if(!K)return ;
scanf("%s",a+); int l1=strlen(a+);
scanf("%s",b+); int l2=strlen(b+);
n=l1+l2+;
for(int i=;i<=l1;i++)s[i]=a[i]; s[l1+]='z'+;
for(int i=;i<=l2;i++)s[l1++i]=b[i];
m=; work(); get();
ll ans=;
ll sum=; top=;
for(int i=,y;i<=n;i++)
{
cnt[i]=;
if(ht[i]<K){top=; sum=; continue;}//min<K
while(ht[i]<ht[y=sta[top]]&&top)
{
sum-=(ll)cnt[y]*(ht[y]-K+);
sum+=(ll)cnt[y]*(ht[i]-K+);//
top--; cnt[i]+=cnt[y];
}
sta[++top]=i;
if(sa[i-]>l1+)sum+=ht[i]-K+,cnt[i]++;//cal(i-1):ht[i]
if(sa[i]<=l1)ans+=sum;
}
sum=; top=;
for(int i=,y;i<=n;i++)
{
cnt[i]=;
if(ht[i]<K){top=; sum=; continue;}//min<K
while(ht[i]<ht[y=sta[top]]&&top)
{
sum-=(ll)cnt[y]*(ht[y]-K+);
sum+=(ll)cnt[y]*(ht[i]-K+);
top--; cnt[i]+=cnt[y];
}
sta[++top]=i;
if(sa[i-]<=l1)sum+=ht[i]-K+,cnt[i]++;
if(sa[i]>l1+)ans+=sum;
}
printf("%lld\n",ans);
}
return ;
}

poj 3415 Common Substrings —— 后缀数组+单调栈的更多相关文章

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

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

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

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

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

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

  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. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

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

  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【SA+单调栈】

    把两个串中间加一个未出现字符接起来,然后求SA 然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献 两部分分别作 ...

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

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

随机推荐

  1. Asp.Net北大青鸟总结(四)-使用GridView实现真假分页

    这段时间看完了asp.net视频.可是感觉到自己的学习好像没有巩固好,于是又在图书馆里借了几本关于asp.net的书感觉真的非常好自己大概对于asp.net可以实现主要的小Demo.可是我知道仅仅有真 ...

  2. java多线程那些事之中的一个

    1.  Callable 接口 获取线程运行状态(get.get(long timeout)),取消线程(cancel(boolean  mayinterruptifrunning)).isCance ...

  3. 帝国CMS万能标签ecmsinfo介绍

    带模板的信息调用标签:[万能标签](ecmsinfo) 标签名称: 带模板的信息调用标签 (sys_GetEcmsInfo) 格式:[ecmsinfo]栏目ID/专题ID, 显示条数, 标题截取数, ...

  4. Windows上搭建Kafka

    搭建环境: 1,安装JDK JAVA_HOME: C:\Program Files (x86)\Java\jre1.8.0_60(这个是默认安装路径,如果安装过程中更改了安装目录,把更改后的路径填上就 ...

  5. EasyPlayerPro Windows播放器电子放大/局部放大播放功能实现

    背景描述 在视频监控软件中,我们看到很多的软件都有电子放大功能, 按住鼠标左键不放,框选一个区域,再松开鼠标左键,即对选中的区域进行放大显示, 且可以重复该操作,逐步放大所需显示的区域, 有没有觉得, ...

  6. 九度OJ 1027:欧拉回路 (欧拉回路)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2989 解决:1501 题目描述:     欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是 ...

  7. iOS视频直播用到的协议

    一 .流媒体 1 - 伪流媒体 1.1 扫盲:边下载边播放1.2 伪流媒体:视频不是实时播放的,先把视频放在数据库,再供客户端访问,比如:优酷,爱奇艺等 1.3 特点: 边下边存,文件会保存.遵守了 ...

  8. Smarty入门学习

    --------------------------------- 安装和设置 --------------------------------- require('../Smarty/Smarty. ...

  9. 【Linux】服务器之间的免密登录脚本

    在实际运维的过程中,经常需要用到免密登录,下面这个脚本实现服务器之间的免密登录,如下 比如,要实现A服务器与B.C.D服务器的免密登录,只需要将B.C.D服务器的IP地址写在serverlist.tx ...

  10. Java for LeetCode 111 Minimum Depth of Binary Tree

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...