【题目分析】

判断有多少个长度不小于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. [从产品角度学EXCEL 01]-EXCEL是怎样运作的

    这是<从产品角度学EXCEL>系列第二篇. 前言请看:从产品角度学EXCEL-系列0-为什么要关注EXCEL的本质 本文不接受无授权转载,如需转载,请先联系我,非常感谢. 1.EXCEL是 ...

  2. STM32f10xxx 之 GPIO口配置

    背景 配置stm32f103使其完成PWM输出的过程中,在配置GPIO口的时候,按照习惯配置GPIO口的speed为50MHZ,突然就意识到,为什么大部分例程习惯配置为50MHZ,而不是其它值,即有了 ...

  3. NDK 笔记(一)

    参考:https://developer.android.com/studio/projects/add-native-code.html#link-gradle 使用Android Studio 2 ...

  4. 数据库 'xxx 的事务日志已满。若要查明无法重用日志中的空间的原因,请参阅 sys.databases 中的 log_reuse_wait_desc 列。

    ---清空日志: USE [master] GO ALTER DATABASE cits SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE cits ...

  5. 关于C#联接数据库是出现'未在本地计算机上注册'错误的解决办法

    今天在用c#连接access数据库处理数据的时候遇到了一个诡异的问题, 未在本地计算机上注册"Microsoft.ACE.OLEDB.12.0"提供程序 我们的部分代码如下: st ...

  6. 排序算法总结------选择排序 ---javascript描述

    每当面试时避不可少谈论的话题是排序算法,上次面试时被问到写排序算法,然后脑袋一懵不会写,狠狠的被面试官鄙视了一番,问我是不是第一次参加面试,怎么可以连排序算法都不会呢?不过当时确实是第一次去面试,以此 ...

  7. PYTHON文件操作(二)

    class file(object) def close(self): # real signature unknown; restored from __doc__ 关闭文件 "" ...

  8. Ternary Expression Parser

    Given a string representing arbitrarily nested ternary expressions, calculate the result of the expr ...

  9. 离线安装 Python 2.7, paramiko 和 tornado

    无非就是离线安装, 步骤比较繁琐, 记录一下. 需求很简单, 一个离线安装的 Python, 能跑 tornado 和 paramiko 1. 离线安装 Python 2.7 .tgz cd Pyth ...

  10. - >code vs 1475 m进制转十进制

    1475 m进制转十进制  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解  查看运行结果   题目描述 Description 将m进制数n转化成一个 ...