【题目分析】

判断有多少个长度不小于k的相同子串的数目。

N^2显然是可以做到的。

其实可以维护一个关于height的单调栈,统计一下贡献,就可以了。

其实还是挺难写的OTZ。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 300005
#define LL long long
#define inf 0x3f3f3f3f
#define F(i,j,k) for (LL i=j;i<=k;++i)
#define D(i,j,k) for (LL i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("wa.txt","w",stdout);
    #endif
}

LL Getint()
{
    LL x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

char ss[maxn];
LL n,l1,l2,k;

struct SuffixArray{
	LL s[maxn];
	LL rk[maxn],h[maxn],cnt[maxn],tmp[maxn],sa[maxn];
	void init()
	{
		memset(s,0,sizeof s);
//		memset(rk,0,sizeof rk);
//		memset(h,0,sizeof h);
//		memset(cnt,0,sizeof cnt);
//		memset(tmp,0,sizeof tmp);
//		memset(sa,0,sizeof sa);
	}
	void build(LL n,LL m)
	{
		LL i,j,k; n++;
		F(i,0,2*n+5) rk[i]=h[i]=tmp[i]=sa[i]=0;
		F(i,0,m-1) cnt[i]=0;
		F(i,0,n-1) cnt[rk[i]=s[i]]++;
		F(i,1,m-1) cnt[i]+=cnt[i-1];
		F(i,0,n-1) sa[--cnt[rk[i]]]=i;
		for (k=1;k<=n;k<<=1)
		{
			F(i,0,n-1)
			{
				j=sa[i]-k;
				if (j<0) j+=n;
				tmp[cnt[rk[j]]++]=j;
			}
			sa[tmp[cnt[0]=0]]=j=0;
			F(i,1,n-1)
			{
				if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
				sa[tmp[i]]=j;
			}
			memcpy(rk,sa,n*sizeof(LL));
			memcpy(sa,tmp,n*sizeof(LL));
			if (j>=n-1) break;
		}
		for (j=rk[h[i=k=0]=0];i<n-1;++i,++k)
			while (~k&&s[i]!=s[sa[j-1]+k]) h[j]=k--,j=rk[sa[j]+1];
		//Debug
		/*
		F(i,0,n-1) cout<<s[i]<<" "; cout<<endl;
		F(i,0,n-1) cout<<sa[i]<<" ";cout<<endl;
		F(i,0,n-1) cout<<h[i]<<" ";cout<<endl;
		*/
		//Debug over
	}
	LL sta[maxn][2],top;
	LL tot,sum;
	void solve(LL n,LL k)
	{
//		n++;
		top=0;sum=0;tot=0;
		F(i,1,n)
		{
			if (h[i]<k) top=tot=0;
			else
			{
				LL cnt=0;
				if (sa[i-1]<l1) cnt++,tot+=h[i]-k+1;
				while (top>0&&h[i]<=sta[top-1][0])
				{
					top--;
					tot-=sta[top][1]*(sta[top][0]-h[i]);
					cnt+=sta[top][1];
				}
				sta[top][0]=h[i]; sta[top++][1]=cnt;
				if (sa[i]>l1) sum+=tot;
			}
		}
		top=tot=0;
		F(i,1,n)
		{
			if (h[i]<k) top=tot=0;
			else
			{
				LL cnt=0;
				if (sa[i-1]>l1) cnt++,tot+=h[i]-k+1;
				while (top>0&&h[i]<=sta[top-1][0])
				{
					top--;
					tot-=sta[top][1]*(sta[top][0]-h[i]);
					cnt+=sta[top][1];
				}
				sta[top][0]=h[i]; sta[top++][1]=cnt;
				if (sa[i]<l1) sum+=tot;
			}
		}
		cout<<sum<<endl;
	}
}arr;

int main()
{
    Finout();
    while (scanf("%lld",&k)!=EOF&&k)
    {
    	arr.init();
    	memset(ss,0,sizeof ss);
    	scanf("%s",ss);l1=strlen(ss);//cout<<l1<<endl;
    	F(i,0,l1-1) arr.s[i]=ss[i];
    	arr.s[l1]=248;
    	memset(ss,0,sizeof ss);
    	scanf("%s",ss);l2=strlen(ss);//cout<<l2<<endl;
    	F(i,0,l2-1) arr.s[l1+i+1]=ss[i];
    	arr.build(l1+l2+1,250);
    	arr.solve(l1+l2+1,k);
	}
}

  

POJ 3415 Common Substrings ——后缀数组的更多相关文章

  1. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  2. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  3. POJ 3415 Common Substrings 后缀数组+并查集

    后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height   求完之后按height值从大往小合并.  height值代表的是  sa[i]和sa[i ...

  4. POJ - 3415 Common Substrings (后缀数组)

    A substring of a string T is defined as: T( i, k)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|. Given two s ...

  5. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  6. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  7. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

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

  8. POJ.3145.Common Substrings(后缀数组 倍增 单调栈)

    题目链接 \(Description\) 求两个字符串长度不小于k的公共子串对数. \(Solution\) 求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}( ...

  9. POJ 3415 Common Substrings(后缀数组 + 单调栈)题解

    题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...

随机推荐

  1. iOS多线程-RunLoop简介

    什么是RunLoop? 从字面上来看是运行循环的意思. 内部就是一个do{}while循环,在这个循环里内部不断的处理各种任务(比如:source/timer/Observer) RunLoop的存在 ...

  2. mysql 快速简单安装法

    网上下载的编译好的包 最好安装在 /usr/local 目录下面: 我用的mysql的版本的是:mysql--linux-i686-icc-glibc23.tar.gz 在官网上就可以下载到. 先期工 ...

  3. 如何在ARM中创建Express Route

    很早之前就想试试Azure的express route,但是一直没有找到合适的机会,正好有个客户需要上express route,所以最近先自己研究研究,防止在做poc的时候耗费更多时间,本次场景我们 ...

  4. php curl 多线程方法

    <?php /** * curl 多线程 * @param array $array 并行网址 * @param int $timeout 超时时间 * @return array */ fun ...

  5. Ajax跨域:jsonp还是CORS

    跨域一般用jsonp,兼容性比较好.CORS是html5最新的XHR第二版本,不支持IE8,IE9,对移动端的支持非常好.但是考虑项目后期这部分会转到同域名下,而且网址不需要支持ie8,ie9,所以我 ...

  6. 触发bfd 的条件

    满足下列条件之一就可触发BFC [1]根元素,即HTML元素 [2]float的值不为none [3]overflow的值不为visible [4]display的值为inline-block.tab ...

  7. 【bb平台刷课记】wireshark结合实例学抓包

    [bb平台刷课记]wireshark结合实例学抓包 背景:本校形势与政策课程课需要在网上观看视频的方式来修得学分,视频网页自带"播放器不可快进+离开窗口自动暂停+看完一集解锁下一集(即不能同 ...

  8. 使用KRPano资源分析工具一键下载全景网站切片图

    软件交流群:571171251(软件免费版本在群内提供) krpano技术交流群:551278936(软件免费版本在群内提供) 最新博客地址:blog.turenlong.com 限时下载地址:htt ...

  9. 进程管理supervisor的简单说明

    背景: 项目中遇到有些脚本需要通过后台进程运行,保证不被异常中断,之前都是通过nohup.&.screen来实现,带着能否做一个start/stop/restart/reload的服务启动的想 ...

  10. Swift 备忘单和快速参考

    Variables var myInt = var myExplicitInt: Int = // explicit type var x = , y = , z = // declare multi ...