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 后缀数组论文题... ...
随机推荐
- 轻松应对C10k问题
http://blog.csdn.net/u011011917/article/details/17203539 传统的.教科书里的I/O复用等待函数select/poll在处理数以万计的客户端连接时 ...
- Java Web应用启动间隔执行的程序
Reference:<Java定时器timer.schedule在Web中间隔执行任务和定时><[Java]Timer和TimerTask详解> 做了一个Demo,完成如下的功 ...
- IOS分类(Category)
分类(Category):拓展原有类的方法,而不影响原有类的子类,分类中不能创建成员变量. 分类的使用: 1.创建分类: 如图点击(File)选择(New)->(File).. 或者使用快捷键c ...
- windows phone 8 设置锁屏背景
本来想研究一下 利用闪光灯实现手电筒的代码,发现不是简答设置FlashMode属性可以解决问题的,ms也没有提供api,无意瞄了一眼侧边栏的文章列表,发现了设置屏幕锁屏背景的实现,手一抖点进去了.还算 ...
- C++11中新特性之:unordered_map
unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value. 不同的是unordered_map不会根据key的大小进行排序,存储时是根据key的ha ...
- 01_C语言基础
内容提要: 1. C语言概述2. 数据类型.运算符与表达式3. C语言程序结构 4. VC6.0使用练习 知识详解01:C语言的历史 1. C语言与其它语言比较 汇编语言: (1).可直接对硬件进行操 ...
- 《JavaScript高级程序设计》笔记(3):传递参数
待更新... 9.17更新: ECMAScript中所有函数的参数都是按值传递的.也就是说,把函数外部复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样.基本类型值的传递如同基本类型变量的复 ...
- JavaScript语言用10张图
JavaScript 语言基础知识点总结,用图片树形结构说明.包括Windows对象.JavaScriptDOM基本操作.JavaScript变量.JavaScript数据类型.JavaScript运 ...
- 以查询方式实现1s定时
以查询控制器的控制位状态来实现1s定时. #include <reg52.h> sbit LED = P0^; unsigned ; void main () { LED = ; // 点 ...
- ios8.1.2耗电情况严重的解决方法
打开cydia,搜索ifile(威锋源,版本2.1.0-1).打开ifile,进入路径/Applications.里面有许多程序文件,选择适当的进行禁用(ifile可以禁用程序的活动而不完全删除它,这 ...