poj3415
很久以前写的,忘补结题报告了
两串相连中间用特殊的分隔符
然后求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的更多相关文章
- 【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≤ ...
- poj3415(后缀数组)
poj3415 题意 给定两个字符串,给出长度 \(m\) ,问这两个字符串有多少对长度大于等于 \(m\) 且完全相同的子串. 分析 首先连接两个字符串 A B,中间用一个特殊符号分割开. 按照 \ ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- 【POJ3415】Common Substrings(后缀数组,单调栈)
题意: n<=1e5 思路: 我的做法和题解有些不同 题解是维护A的单调栈算B的贡献,反过来再做一次 我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去 式子展开之后 ...
- POJ3415 Common Substrings(后缀数组 单调栈)
借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...
- poj3415 Common Substrings(后缀数组,单调栈 | 后缀自动机)
[题目链接] http://poj.org/problem?id=3415 [题意] A与B长度至少为k的公共子串个数. [思路] 基本思想是将AB各个后缀的lcp-k+1的值求和.首先将两个字符串拼 ...
- POJ3415 Common Substrings
后缀数组 求长度不小于k的公共子串的个数 代码: #include <stdio.h> #include <string.h> ; int len, len1; int wa[ ...
- 2018.12.15 poj3415 Common Substrings(后缀自动机)
传送门 后缀自动机基础题. 给两个字符串,让你求长度不小于kkk的公共子串的数量. 这题可以用后缀自动机解决废话 考虑对其中一个字串建出后缀自动机,然后用另一个在上面跑,注意到如果一个状态有贡献的话, ...
- 【poj3415】 Common Substrings
http://poj.org/problem?id=3415 (题目链接) 题意 给定两个字符串 A 和 B,求长度不小于 k 的公共子串的个数(可以相同). Solution 后缀数组论文题... ...
随机推荐
- 那天有个小孩跟我说LINQ(二)转载
1 LINQ TO Objects续(代码下载) 新建项目 linq_Ch2控制台程序,新建一个Entity文件夹 1.1 学生成绩查询(练习Join) 有三张表如下 ...
- C#获取当前路径,获取当前路径的上一层路径
C#获取当前路径的方法如下: (1)string path1 = System.Environment.CurrentDirectory; //C:\...\bin\Debug -获取和设置当前工作目 ...
- 写漂亮C#代码的小技巧
第一次写博客,不知道代码用什么编辑,直接截图了,哈哈哈.... 我自己不喜欢看随便复制粘贴过来一堆代码的博客,所以,用些简单点的例子吧,希望对大家有帮助... ------------------- ...
- 在终端里使用 Solarized 配色方案
在终端里使用 Solarized 配色方案 参考: 1.在 Mac OS X 终端里使用 Solarized 配色方案 2.solarized
- IOS 学习笔记 2015-04-09 0C-SQLite 数据存储
1 项目导入 libsqlite3.0.dylib 框架 2 在使用数据sqlite的头文件(.h)上导入 #Impourt <sqlite3.h> 3 推荐自己本地电脑下个sqlite ...
- android BitmapFacty.Options的用法
通常我们在开发android应用程序时,在加载图片时常常需要与Bitmap打交道,一般会使用BitmapFactory中提供的相关decode方法获取: 如果一张很大的图片,我们不加处理直接decod ...
- 点击listview 的列头对其item进行自动排序
若要自定义排序顺序,必须编写一个实现 IComparer 接口的类,并将 ListViewItemSorter 属性设置为该类的一个对象.当设置 ListViewItemSorter 属性值时,将自动 ...
- 将选择的图片显示在listview中,并显示filename,path和type
if (openFileDialog1.ShowDialog() == DialogResult.OK) { listView1.Items.Clear(); string[] files = ope ...
- skymvc文件上传支持多文件上传
skymvc文件上传支持多文件上传 支持单文件.多文件上传 可以设定 文件大小.存储目录.文件类型 //上传的文件目录 $this->upload->uploaddir="att ...
- Windows下MySQL数据库备份脚本(一)
说明: MySQL数据库安装目录:C:\Program Files\MySQL\MySQL Server 5.0 MySQL数据库存放目录:C:\Program Files\MySQL\MySQL S ...