记录编号 163805 评测结果 AAAAAAAAAA
题目名称 [POJ3415]公共子串 最终得分 100
用户昵称 Gravatarztx 是否通过 通过
代码语言 C++ 运行时间 3.139 s
提交时间 2015-05-26 17:22:57 内存使用 24.32 MiB
显示代码纯文本
/****************************************\
* Author : ztx
* Title  : [cogs] 1712. [POJ3415]公共子串
* ALG    : SAM
* CMT    :
* Time   :
\****************************************/

#include <cstdio>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
typedef long long ll ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}
template <typename TP>inline void readc(TP& ret) {
	while (ret=getchar() , ret<'!') ;
	while (CH=getchar() , CH>'!') ;
}
template <typename TP>inline void reads(TP *ret) {
	ret[0]=0;while (CH=getchar() , CH<'!') ;
	while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;
	ret[ret[0]+1]=0;
}

#include <cstring>

#define  max(x,y) ((x)>(y)?(x):(y))

namespace Suffix_Automaton {
	#define  maxl  100010LL
	#define  maxt  200010LL
	#define  maxc  26LL
	struct SAM { int f,l,right,cnt,c[maxc]; } sam[maxt] ;
	int root = 1 , sink = 1 , tott = 1 , len = 0 ;
	inline void SAM_init() {
		memset(sam , 0 , sizeof sam) ;
		root = sink = tott = 1 ;
		len = 0 ;
	}
	inline void SAM_insert(int x) {
		int p , q , nq ;
		p = sink , sink = ++tott , len ++ ;
		sam[sink].l = sam[p].l+1 ;
		sam[sink].right = 1 ;
		for (; p && !sam[p].c[x] ; p=sam[p].f) sam[p].c[x] = sink ;
		if (!p) sam[sink].f = root ;
		else {
			q = sam[p].c[x] ;
			if (sam[p].l+1 == sam[q].l) sam[sink].f = q ;
			else {
				sam[nq=++tott] = sam[q] ;
				sam[nq].l = sam[p].l+1 ;
				sam[nq].right = 0 ;
				sam[q].f = sam[sink].f = nq ;
				for (; p && sam[p].c[x]==q ; p=sam[p].f) sam[p].c[x] = nq ;
			}
		}
	}
	int ws[maxt] = {0} , wv[maxl] = {0} ;
	inline void SAM_gr() {
		int i , p , fp ;
		Rep (i,1,len)  wv[i] = 0 ;
		Rep (i,1,tott) wv[sam[i].l] ++ ;
		Rep (i,1,len)  wv[i] += wv[i-1] ;
		Rep (i,1,tott) ws[wv[sam[i].l]--] = i ;
		Rev (i,tott,1) p = ws[i] , fp = sam[p].f , sam[fp].right += sam[p].right ;
	}
	#undef  maxl
	#undef  maxt
	#undef  maxc
}

using namespace Suffix_Automaton ;

int main() {
int K , x , i , p , fp , now ;
ll ans ;
	#define READ
	#ifdef  READ
		freopen("commonsubstrings.in" ,"r",stdin ) ;
		freopen("commonsubstrings.out","w",stdout) ;
	#endif
	while (read(K) , K) {
		SAM_init() ;
		while (CH=getchar(),CH<'!') ;
		while (SAM_insert(CH-'a'),CH=getchar(),CH>'!') ;
		SAM_gr() ;
		while (CH=getchar(),CH<'!') ;
		ans = 0 ;
		for (p = root , now = 0 ; CH>'!' ; CH=getchar()) {
			x = CH-'a' ;
			if (sam[p].c[x]) p = sam[p].c[x] , now ++ ;
			else {
				for ( ; p && !sam[p].c[x] ; p = sam[p].f) ;
				if (!p) now = 0 , p = root ;
				else now = sam[p].l+1 , p = sam[p].c[x] ;
			}
			fp = sam[p].f ;
			if (now >= K) {
				ans += (ll)(now-max(K,sam[fp].l+1)+1)*sam[p].right ;
				/* 第一次计算,只计算了LCS>=K时的情形,并在此时标记fp的cnt */
				if (K <= sam[fp].l) sam[fp].cnt ++ ;
			}
		}
		Rev (i,tott,1) {
			p = ws[i] , fp = sam[p].f ;
			ans += (ll)sam[p].cnt*(sam[p].l-max(K,sam[fp].l+1)+1)*sam[p].right ;
			/* 第二次计算,计算非LCS但符合要求的数量,topo计算cnt */
			if (K <= sam[fp].l) sam[fp].cnt += sam[p].cnt ;
		}
		printf("%lld\n", ans) ;
	}
	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}