【题目分析】

判断有多少个长度不小于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. 成功开发iPhone软件的10个步骤

    总结 几条要注意的原则: 1.了解你的用户,并与他们接触.交谈. 2.不要做虚幻的想象的设计,多从成功软件中汲取经验. 3.软件要设计得“小”. 4.找到足够多的设计方案,通过数量的累计来得到好的质量 ...

  2. Greenplum-概念篇

    Greenplum主要组件包括:Master.Segments.Interconnect:其他组件包括ETL Server.Greenplum command center等.0. 组件之-Maste ...

  3. Android ActionBar 初探

    1.指南,例子,个人感觉 首先上官网指南链接http://developer.android.com/guide/topics/ui/actionbar.html 参考了官网上的例子http://de ...

  4. UI第十七节——UIScrollView

    // 实例化一个ScrollView    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen main ...

  5. eclipse常用快捷键

    1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xm ...

  6. Django Restful Framework (一): Serializer

    Serializer 允许复杂数据(比如 querysets 和 model 实例)转换成python数据类型,然后可以更容易的转换成 json 或 xml 等.同时,Serializer也提供了反序 ...

  7. bzoj3481题解

    答案等于$\sum_{d|(P,Q)} d\times \varphi (P/d)$设$P=\prod_{i=1}^t p_i^{m_i}$,$P=\prod_{i=1}^t p_i^{k_i}$答案 ...

  8. Circular Buffer

    From:http://bradforj287.blogspot.com/2010/11/efficient-circular-buffer-in-java.html import java.util ...

  9. 关于so文件cp覆盖导致调用者core的研究

    先说cp好mv/rm的区别: cp from to,则被覆盖文件 to的inode依旧不变(属性也不变),内容变为from的: mv from to,则to的inode变为from的,相应的,to的属 ...

  10. ZOJ 3871 Convex Hull(计算几何、凸包)

    题意:给n个点,|x[i]|,|y[i]| <= 1e9.求在所有情况下的子集下(子集点数>=3),凸包的面积和. 这题主要有几个方面,一个是凸包的面积,可以直接用线段的有向面积和求得,这 ...