POJ3415 Common Substrings(后缀数组 单调栈)
借用罗穗骞论文中的讲解:
计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来。先将两个字符串连起来,中间用一个没有出现过的字符隔开。按height 值分组后,接下来的工作便是快速的统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个B 的后缀就统计与前面的A 的后缀能产生多少个长度不小于k 的公共子串,这里A 的后缀需要用一个单调的栈来高效的维护。然后对A 也这样做一次。
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cstdlib>
- using namespace std;
- const int N = 210008;
- typedef long long LL;
- int val[N], sum[N], wa[N], wb[N];
- int sa[N], rk[N], height[N];
- char a[N], b[N];
- inline bool cmp(int str[], int a, int b, int l){
- return str[a] == str[b] && str[a + l] == str[b + l];
- }
- void da(char str[], int n, int m){
- int *x = wa, *y = wb;
- memset(sum, 0, sizeof(sum));
- for(int i = 0; i < n; i++){
- sum[x[i] = str[i]]++;
- }
- for(int i = 1; i < m; i++){
- sum[i] += sum[i - 1];
- }
- for(int i = n - 1; i >= 0; i--){
- sa[--sum[ x[i]] ] = i;
- }
- for(int j = 1, p = 1; p < n; j *= 2, m = p){
- p = 0;
- for(int i = n - j; i < n; i++){
- y[p++] = i;
- }
- for(int i = 0; i < n; i++){
- if(sa[i] >= j){
- y[p++] = sa[i] - j;
- }
- }
- for(int i = 0; i < n; i++){
- val[i] = x[ y[i] ];
- }
- memset(sum , 0, sizeof(sum));
- for(int i = 0; i < n; i++){
- sum[val[i]]++;
- }
- for(int i = 1; i < m; i++){
- sum[i] += sum[i - 1];
- }
- for(int i = n - 1; i >= 0; i--){
- sa[--sum[ val[i] ]] = y[i];
- }
- swap(x, y);
- x[sa[0]] = 0;
- p = 1;
- for(int i = 1 ; i < n; i++){
- x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1:p++;
- }
- }
- }
- void getHeight(char str[], int n){
- for(int i = 1; i <= n; i++){
- rk[ sa[i] ] = i;
- }
- int k = 0;
- for(int i = 0; i < n; height[rk[i++]] = k){
- if(k) k--;
- int j = sa[rk[i] - 1];
- while(str[i + k] == str[j + k]){
- k++;
- }
- }
- }
- struct node{
- int h;
- LL cnt;
- }stk[N];
- int main(){
- int k;
- while(~scanf("%d", &k) && k){
- scanf("%s %s", a, b);
- int n = strlen(a);
- int m = strlen(b);
- int len = n + m + 1;
- a[n] = 125;
- for(int i = n + 1, j = 0; j < m; i++, j++){
- a[i] = b[j];
- }
- a[len] = 0;
- da(a, len + 1, 150);
- getHeight(a, len);
- LL sum = 0;
- int top = 0;
- LL tot = 0;
- for(int i = 1; i <= len ; i++){
- int cnt = 0;
- if(height[i] < k){
- top = 0;
- tot = 0;
- }else{
- if(sa[i - 1] < n){
- cnt++;
- tot += height[i] - k + 1;
- }
- while(top > 0 && stk[top - 1].h > height[i]){
- top--;
- cnt += stk[top].cnt;
- tot -= (stk[top].h - height[i]) * stk[top].cnt;
- }
- stk[top].h = height[i];
- stk[top].cnt = cnt;
- top++;
- if(sa[i] > n){
- sum += tot;
- }
- }
- }
- top = 0;
- tot = 0;
- for(int i = 1; i <= len ; i++){
- int cnt = 0;
- if(height[i] < k){
- top = 0;
- tot = 0;
- }else{
- if(sa[i - 1] > n){
- cnt++;
- tot += height[i] - k + 1;
- }
- while(top > 0 && stk[top - 1].h > height[i]){
- top--;
- cnt += stk[top].cnt;
- tot -= (stk[top].h - height[i]) * stk[top].cnt;
- }
- stk[top].h = height[i];
- stk[top].cnt = cnt;
- top++;
- if(sa[i] < n){
- sum += tot;
- }
- }
- }
- printf("%I64d\n", sum);
- }
- return 0;
- }
POJ3415 Common Substrings(后缀数组 单调栈)的更多相关文章
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- poj3415 Common Substrings (后缀数组+单调队列)
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 9414 Accepted: 3123 Description A sub ...
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
随机推荐
- Github GUI 托管代码教程
附录:克隆仓库到本地:git clone https://github.com/chzeze/WeiboHomeCrawl.git
- MD5 加密字符串
public class MD5 { /*** * MD5加码 生成32位md5码 */ public static String string2MD5(String inStr){ MessageD ...
- C#的is和as操作符来进行强制类型转换&&值类型的拆箱、装箱
if(o is Employee) { Employee e=(Employee)o; //在if语句剩余的部分中使用e; } Employee e=o as Employee; if(e!=null ...
- Java中 final static super this instanceof 关键字用法
一.final关键字 final可以修饰变量.方法及类: 1.当定义一个final变量时,jvm会将其分配到常量池中,其所修饰的对象只能赋值一次,对基本类型来说是其值不可变,引用类型(包括作为函数形参 ...
- java web 学习 --第十天(Java三级考试)
第九天学习内容:http://www.cnblogs.com/tobecrazy/p/3470195.html 需求概述 创建程序模块,读取并显示数据库中的书籍信息.当前有如下需求:需要显示数据库中所 ...
- bind+dlz+mysql实现区域记录动态更新
BIND-DLZ实验:http://bind-dlz.sourceforge.net/ 实验环境:RHEL4,BIND-9.5.0-P2.tar.gz(9.4.0以上版本都已含DLZ补丁),Mysql ...
- Centos6.5 SVN服务器 搭建及配置
现有的项目开发中,版本控制机必不可少.合理的使用版本控制可以提高开发效果,在保证项目是最新的同时,也提高了源代码的安全性. 工具/原料 接入Internet的一台Centos6.5Linux计算机 安 ...
- 好用的php类库和方法
1, /** * 将一个平面的二维数组按照指定的字段转换为树状结构 * * 用法: * @code php * $rows = array( * array('id' => 1, 'value' ...
- osg 纹理访问器
#include<osgViewer/Viewer> #include<osg/Node>#include<osg/Geode>#include<osg/Gr ...
- SQL存储过程大全
--增加 create proc usp_insertToText ), ), @usitPrice decimal as begin insert into TEST1 output inserte ...