很久以前写的,忘补结题报告了
两串相连中间用特殊的分隔符
然后求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. Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法

    Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...

  2. iOS-开发记录-UIView属性

    UIView属性 1.alpha 设置视图的透明度.默认为1. // 完全透明 view.alpha = ; // 不透明 view.alpha = ; 2.clipsToBounds // 默认是N ...

  3. DataTable.ImportRow()与DataTable.Rows.Add()的区别

    今天写代码的时候用到ImportRow()向DataTable中添加记录,代码如下: DataTable dt = datatable;DataRow dr = dt.NewRow();dr[&quo ...

  4. PHP学习笔记(七)

    <wordpress 50个过滤钩子> 11-20 11.gettext: 过滤wordpress的翻译数据. 在wordpress中,使用__(), _e(), _x(), _ex(), ...

  5. ReactNative-----环境搭建二(android)

    一.初始化一个ReactNative项目 在指定目录运行命令:react-native init Vince(项目名称)  //其过程就是在使用CLI工具构建项目, 命令行代码 F:\React> ...

  6. 10.21_Nutz批量插入顺序,POI,wiki持续关注,POI,SSH,数据库优先

    (1)Nutz,dao的批量插入会关注顺序吗? http://www.douban.com/group/topic/64322582/ (2)工作需要优先!!!  POI,SSH,数据库管理及plsq ...

  7. 无责任共享 Coursera、Udacity 等课程视频

    本文转载自网络,原作者不详. (本文是用 markdown 写的,访问 https://www.zybuluo.com/illuz/note/71868 获得更佳体验) 程序语言 interactiv ...

  8. HeadFirst设计模式

    oo基础 抽象 封装 多态 继承 oo原则 封装变化 多用组合,少用继承 针对接口编程,不针对实现编程(策略模式) 为交互对象之间的松耦合设计而努力(观察者模式) 对扩展开放,对修改关闭(装饰者模式) ...

  9. Linux网络应用编程之集线器(Packet Tracer仿真)

    Packet Tracer入门 一,集线器概况 对接收到的信号进行再生整形放大,以扩大网络的传输距离,同时把所有节点集中在以它为中心的节点上. 工作于OSI(开放式系统互联参考模型)的最底层(物理层) ...

  10. 【原创】Android开发使用华为手机调试logcat没有应用输出信息

    输入 *#*#2846579#*#* 点击project Menu点击后台 1.设置logcat 2. Dump & Log",打开开关"打开Dump & Log& ...