很久以前写的,忘补结题报告了
两串相连中间用特殊的分隔符
然后求height,由于要求求公共子串大于等于k的个数,并且只要位置不同即可
因此不难想到在名次上对height分组,一组内的height保证>=k
下面就是在组内统计的问题了
然后还是不难发现,分别在AB串中的后缀i,j,他们能产生2*[LCP(i,j)-k+1]个公共子串
然后那个著名的性质LCP(i,j)=min(h[rank[i]+1]~h[rank[j]]) (令rank[i]<rank[j])
不难想到维护一个单调增的队列,遇到在B串就统计并维护,遇到在A串就维护
然后再反过来做一遍
具体维护单调队列见程序,否则感觉讲不清

 type node=record
h,s:longint;
end;
var s,ss:ansistring;
h,sa,sum,y,x,rank:array[..] of longint;
n,m,i,j,loc,p,k,t,f:longint;
q:array[..] of node;
w,ans:int64; begin
readln(k);
while k<> do
begin
readln(s);
loc:=length(s)+;
readln(ss);
s:=s+' '+ss;
n:=length(s);
fillchar(sum,sizeof(sum),);
for i:= to n do
begin
y[i]:=ord(s[i]);
inc(sum[y[i]]);
end;
m:=;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[y[i]]]:=i;
dec(sum[y[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if y[sa[i]]<>y[sa[i-]] then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=;
while m<n do
begin
y:=rank;
fillchar(sum,sizeof(sum),);
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i]>j then
begin
inc(p);
x[p]:=sa[i]-j;
end;
for i:= to n do
begin
rank[i]:=y[x[i]];
inc(sum[rank[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[rank[i]]]:=x[i];
dec(sum[rank[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i]+j]<>y[sa[i-]+j]) then inc(p);
rank[sa[i]]:=p;
end;
j:=j shl ;
m:=p;
end;
h[]:=;
p:=;
for i:= to n do
begin
if rank[i]= then continue;
j:=sa[rank[i]-];
while s[i+p]=s[j+p] do inc(p);
h[rank[i]]:=p;
if p> then dec(p);
end; ans:=;
t:=;
f:=;
w:=;
if sa[]<loc then
begin
w:=w+h[]-k+;
q[t].h:=h[];
q[t].s:=;
inc(t);
end;
for i:= to n do
begin
if h[i]>=k then
begin
if sa[i]<loc then
begin
p:=;
w:=w+h[i+]-k+; //w维护组内到下一个在B中的后缀(LCP-k+)和
end
else if sa[i]>loc then
begin
ans:=ans+w;
if i=n then continue;
p:=; //这里注意,这是B串的后缀,不能和下一个B串后缀形成公共子串
end;
while (f<t) and (q[t-].h>=h[i+]) do //队中height比当前大直接退,因为它的height一定不是LCP
begin
w:=w-(q[t-].h-h[i+])*q[t-].s; //s域维护是队列中当前元素到队中前一个元素之间有多少比它height大
//这里显然之前height比当前大的元素和下一个B串后缀可能的LCP都应当是当前h[i+]
p:=p+q[t-].s;
dec(t);
end;
if p> then
begin
q[t].h:=h[i+];
q[t].s:=p;
inc(t);
end;
end
else begin
t:=;
w:=;
f:=;
if sa[i]<loc then
begin
q[t].h:=h[i+];
q[t].s:=;
w:=h[i+]-k+;
inc(t);
end;
end;
end; t:=;
f:=;
w:=;
if sa[]<loc then
begin
w:=w+h[]-k+;
q[t].h:=h[];
q[t].s:=;
inc(t);
end;
for i:= to n do
begin
if h[i]>=k then
begin
if sa[i]>loc then
begin
p:=;
w:=w+h[i+]-k+;
end
else if sa[i]<loc then
begin
ans:=ans+w;
if i=n then continue;
p:=;
end;
while (f<t) and (q[t-].h>=h[i+]) do
begin
w:=w-(q[t-].h-h[i+])*q[t-].s;
p:=p+q[t-].s;
dec(t);
end;
if p> then
begin
q[t].h:=h[i+];
q[t].s:=p;
inc(t);
end;
end
else begin
t:=;
w:=;
f:=;
if sa[i]>loc then
begin
q[t].h:=h[i+];
q[t].s:=;
w:=h[i+]-k+;
inc(t);
end;
end;
end;
writeln(ans);
readln(k);
end;
end.

poj3415的更多相关文章

  1. 【POJ3415】 Common Substrings(后缀数组|SAM)

    Common Substrings Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤ ...

  2. poj3415(后缀数组)

    poj3415 题意 给定两个字符串,给出长度 \(m\) ,问这两个字符串有多少对长度大于等于 \(m\) 且完全相同的子串. 分析 首先连接两个字符串 A B,中间用一个特殊符号分割开. 按照 \ ...

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

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

  4. 【POJ3415】Common Substrings(后缀数组,单调栈)

    题意: n<=1e5 思路: 我的做法和题解有些不同 题解是维护A的单调栈算B的贡献,反过来再做一次 我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去 式子展开之后 ...

  5. POJ3415 Common Substrings(后缀数组 单调栈)

    借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...

  6. poj3415 Common Substrings(后缀数组,单调栈 | 后缀自动机)

    [题目链接] http://poj.org/problem?id=3415 [题意] A与B长度至少为k的公共子串个数. [思路] 基本思想是将AB各个后缀的lcp-k+1的值求和.首先将两个字符串拼 ...

  7. POJ3415 Common Substrings

    后缀数组 求长度不小于k的公共子串的个数 代码: #include <stdio.h> #include <string.h> ; int len, len1; int wa[ ...

  8. 2018.12.15 poj3415 Common Substrings(后缀自动机)

    传送门 后缀自动机基础题. 给两个字符串,让你求长度不小于kkk的公共子串的数量. 这题可以用后缀自动机解决废话 考虑对其中一个字串建出后缀自动机,然后用另一个在上面跑,注意到如果一个状态有贡献的话, ...

  9. 【poj3415】 Common Substrings

    http://poj.org/problem?id=3415 (题目链接) 题意 给定两个字符串 A 和 B,求长度不小于 k 的公共子串的个数(可以相同). Solution 后缀数组论文题... ...

随机推荐

  1. 界面动态加载时报NullPointException

    今天在做环境监测的模拟软件时,登陆页面报NullPointException 一般像我们初始化Button时,是Button btn=(Button)findViewById(R.id.button1 ...

  2. Servlet相关接口和Servlet的生命周期

    http://www.cnblogs.com/luotaoyeah/p/3860292.html Servlet相关接口和Servlet的生命周期 创建一个Servlet类最直接的方式是实现javax ...

  3. 周末充电之WPF(一).初试牛刀

    追的剧已经赶上更新的速度了,突然觉得一下子就闲了.趁着这点时间,刚好学点 WPF .看到这边,好多人估计得感叹技术宅约等于单身狗,哈哈.好了,赶紧进入学习状态. 关注 WPF 或者说对它感兴趣其实多半 ...

  4. Apache配置命令

    Apache的主配置文件: 1.DocumentRoot——指定网站的根目录 提示:该目录必须存在.目录上不能有汉字或空格. 2.DirectoryIndex (1)描述:设置网站的默认首页文件.访问 ...

  5. 【笔记】mongodb启动不了:child process failed, exited with error number 100

    今天在启动mongodb的时候,发现起不来,报错:child process failed, exited with error number 100然后先去/var/log/mongo/mongod ...

  6. java时间格式大全

    java.util.*;import java.text.*;import java.util.Calendar; public class VeDate { /**  * 获取现在时间  *   * ...

  7. 基于ACE的定时器模板类

    ACETimerClockGenerator.h ClockGeneratorIF.h 在类中定义一个结构体,在结构体中定义一个函数. 在结构体中定义一个函数,这样做有什么好呢? TimerHandl ...

  8. 【原创】解决国内Android SDK无法更新问题更新

    使用代理,推荐使用shadowsock 在SDK Manage的tools-options填好代理 服务器地址127.0.0.1 端口1080

  9. JavaScript经典面试题系列

    1.javascript的typeof返回哪些数据类型 Object number function boolean underfind 2.例举3种强制类型转换和2种隐式类型转换? 强制(parse ...

  10. [转]利用maven的surefire插件实现单元测试与集成测试

    原文链接 http://my.oschina.net/dlpinghailinfeng/blog/301136 maven单元测试与集成测试 通过maven的Profile 配置生命周期 通过mave ...