题目: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. Java中的Enum的继承

    public interface Icolor{ int apply(int x,int y); } public enum color implements Icolor{ plus("+ ...

  2. C++第4次实验(提高班)—继承和派生1

    从项目2和项目3中选1题作为实验.剩下2题写成作业. [项目1 - 龙三] 请在以下程序的横线处填上适当内容,以使程序完整,并使程序的输出为: Name: 龙三 Grade: 19 #include ...

  3. YII框架学习(二)

    YII框架的增删改查 例:一个新闻表的增删改查: (1)首先使用gii工具生成控制器和模型 (2)控制器 <?php class NewsController extends Controlle ...

  4. inclusion_tag 看图

  5. EasyNVR H5无插件摄像机直播解决方案前端解析之:videojs初始化的一些样式处理

    初始化完成对videojs样式的调整 由于不同项目的需要,对于加载出来的videojs播放器样式也有不同的需求:我们需要自主的处理一下加载出来的videojs播放器的样式: 默认加载出来的会包含有暂停 ...

  6. iOS应用上架报错解决

    ERROR ITMS-90087: "Unsupported Architectures. The executable for LiveStorage.app/Frameworks/Spe ...

  7. mybatis 运算符转义收录

    在ibatis配置文件写SQL语句的时候对于一些比如“<”,">","<>","&"," ' &q ...

  8. 【题解】Fence(单调队列)

    [题解]Fence(单调队列) POJ - 1821 题目大意 有\(k\)个粉刷匠,每个粉刷匠一定要粉刷某个位置\(S_i\),一个粉刷匠可以粉刷至多\(l_i\)个位置(必须连续\(l_i\)互不 ...

  9. MySQL基于二进制日志的主从复制

    一.什么是MySQL的主从复制? MySQL可以将一个数据库设置为主库,另一个数据库设置为该主库的从库,当主库发生了变更,会同步到从库中.MySQL的主从架构,可以是星型的,也可以是线型的. 星型架构 ...

  10. 各种python 函数參数定义和解析

    python 中的函数參数是赋值式的传递的,函数的使用中要注意两个方面:1.函数參数的定义过程,2.函数參数在调用过程中是怎样解析的. 首先说一下在python 中的函数调用过程是分四种方式的.这里且 ...