Marlon's String zoj3587

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4629

后缀数组或扩展kmp

SA做法

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream> 
#include <ctime>
#include <bitset>
#include <iomanip>
#pragma comment(linker, "/STACK:102400000,102400000")

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;
using std::ios;
using std::make_heap;
using std::push_heap;
using std::pop_heap;

typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
typedef long double LF;

const int MAXN(200010);
const int MAXM(20010);
const int MAXE(2100010);
const int MAXK(6);
const int HSIZE(1313131);
const int SIGMA_SIZE(26);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
const LF PI(acos(-1.0));

template<typename T> inline bool checkmax(T &a, T b){if(b > a) { a = b; return true;} return false;}
template<typename T> inline bool checkmin(T &a, T b){if(b < a) { a = b; return true;} return false;}
template<typename T> inline T ABS(T a){return a < 0? -a: a;}
template<typename T> inline bool EZ(T a){return ABS(a) < EPS;}

int Log[MAXN];
void initLog(){
	Log[0] = -1;
	for(int i = 1; i < MAXN; ++i) Log[i] = (i&(i-1))? Log[i-1]: Log[i-1]+1;
}

struct SA{
	char S[MAXN];
	int sa[MAXN], t1[MAXN], t2[MAXN], cnt[MAXN], len, M;
	void init(int l, int m = 128){
		len = l;
		M = m;
		int *p1 = t1, *p2 = t2;
		for(int i = 0; i < M; ++i) cnt[i] = 0;
		for(int i = 0; i <= len; ++i) ++cnt[p1[i] = S[i]];
		for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1];
		for(int i = len; i >= 0; --i) sa[--cnt[p1[i]]] = i;
		int temp = 1;
		for(int k = 1; temp <= len; k <<= 1){
			temp = 0;
			for(int i = len-k+1; i <= len; ++i) p2[temp++] = i;
			for(int i = 0; i <= len; ++i) 
				if(sa[i] >= k) p2[temp++] = sa[i]-k;
			for(int i = 0; i < M; ++i) cnt[i] = 0;
			for(int i = 0; i <= len; ++i) ++cnt[p1[p2[i]]];
			for(int i = 1; i < M; ++i) cnt[i] += cnt[i-1];
			for(int i = len; i >= 0; --i) sa[--cnt[p1[p2[i]]]] = p2[i];
			swap(p1, p2);
			temp = 1;
			p1[sa[0]] = 0;
			for(int i = 1; i <= len; ++i)
				p1[sa[i]] = p2[sa[i-1]] == p2[sa[i]] && p2[sa[i-1]+k] == p2[sa[i]+k]? temp-1: temp++;
			M = temp;
		}
	}
	int rank[MAXN], hei[MAXN];
	void getHei(){
		int k = 0;
		for(int i = 0; i <= len; ++i) rank[sa[i]] = i;
		for(int i = 0; i < len; ++i){
			if(k) --k;
			int j = sa[rank[i]-1];
			while(S[i+k] == S[j+k]) ++k;
			hei[rank[i]] = k;
		}
	}
	int dp[MAXH][MAXN];
	void initRMQ(){
		for(int i = 1; i <= len; ++i) dp[0][i] = hei[i];
		for(int i = 1; (1 << i) <= len; ++i)
			for(int j = 1; j+(1 << i)-1 <= len; ++j)
				dp[i][j] = min(dp[i-1][j], dp[i-1][j+(1 << (i-1))]);
	}
	int lcp(int a, int b){
		if(a == b) return len-a;
		if(a == len || b == len) return 0;
		a = rank[a];
		b = rank[b];
		if(a > b) swap(a, b);
		++a;
		int temp = Log[b-a+1];
		return min(dp[temp][a], dp[temp][b-(1 << temp)+1]);
	}
	int solve(int ind, int lim){
		ind = rank[ind];
		int ret = 0;
		int l = 0, r = ind;
		while(l < r){
			int m = (l+r) >> 1;
			if(lcp(sa[m], sa[ind]) >= lim) r = m;
			else l = m+1;
		}
		ret += ind-l+1;
		l = ind, r = len+1;
		while(l < r){
			int m = (l+r) >> 1;
			if(lcp(sa[m], sa[ind]) >= lim) l = m+1;
			else r = m;
		}
		--l;
		ret += l-ind+1;
		--ret;
		return ret;
	}
} sa1, sa2;

int main(){
	initLog();
	int TC;
	scanf("%d", &TC);
	while(TC--){
		scanf("%s%s", sa1.S, sa2.S);
		int len1 = strlen(sa1.S), len2 = strlen(sa2.S);
		sa1.S[len1] = 1;
		strcpy(sa1.S+len1+1, sa2.S);
		sa1.init(len1+len2+1);
		sa2.init(len2);
		sa1.getHei();
		sa2.getHei();
		sa1.initRMQ();
		sa2.initRMQ();
		LL ans = 0;
		for(int i = 1; i < len2; ++i){
			LL t1 = sa1.solve(len1+1, i);
			LL t2 = sa2.solve(0, i);
			LL t3 = t1-t2;
			t1 = sa1.solve(len1+1+i, len2-i);
			t2 = sa2.solve(i, len2-i);
			ans += t3*(t1-t2);
		}
		printf("%lld\n", ans);
	}
	return 0;
}


扩展kmp

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream> 
#include <ctime>
#include <bitset>
#include <iomanip>
#pragma comment(linker, "/STACK:102400000,102400000")

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::stringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
using std::unique;
using std::lower_bound;
using std::random_shuffle;
using std::bitset;
using std::upper_bound;
using std::multiset;
using std::ios;
using std::make_heap;
using std::push_heap;
using std::pop_heap;

typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned UN;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
typedef long double LF;

const int MAXN(100010);
const int MAXM(20010);
const int MAXE(2100010);
const int MAXK(6);
const int HSIZE(1313131);
const int SIGMA_SIZE(26);
const int MAXH(19);
const int INFI((INT_MAX-1) >> 1);
const ULL BASE(31);
const LL LIM(1e13);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
const LF PI(acos(-1.0));

template<typename T> inline bool checkmax(T &a, T b){if(b > a) { a = b; return true;} return false;}
template<typename T> inline bool checkmin(T &a, T b){if(b < a) { a = b; return true;} return false;}
template<typename T> inline T ABS(T a){return a < 0? -a: a;}
template<typename T> inline bool EZ(T a){return ABS(a) < EPS;}
/*
template<typename TY, int N>
struct EXKMP{
	TY P[N];
	int lenp;
	int next[N];
	void getnext(){
		next[0] = lenp;
		int k = 1, l = 0, a = 1;
		while(k < lenp && P[k] == P[l]){
			++k;
			++l;
		}
		next[l] = 1;
		int i = 2;
		while(i < lenp){
			int temp = next[i-a];
			if(i+temp < k) next[i] = temp;
			else{
				checkmax(k, i);
				l = k-i;
				while(k < lenp && P[k] == P[l]){
					++k;
					++l;
				}
				next[i] = l;
				a = i;
			}
			++i;
		}
		next[lenp] = 0;
	}
	TY T[N];
	int lent;
	int extend[N];
	void getextend(){
		int i, a, p, j(-1);
		for(i = 0; i < lent; ++i, --j){
			if(j < 0 || i+next[i-a] >= p){
				if(j < 0) j = 0, p = i;
				while(p < lent && j < lenp && T[p] == P[j]) ++p, ++j;
				extend[i] = j, a = i;
			}
			else
				extend[i] = next[i-a];
		}
	}
};
*/
template<typename TY, int N>
struct EXKMP
{
	TY P[N];
	int lenp;
	int next[N]; //next[i]表示str[i...len-1] 与 str[0...len-1]的最长公共前缀
	void getnext()
	{
		next[0] = lenp;
		int k = 1, l = 0, a = 1; //含义: 当前位置, 匹配长度
		while(k < lenp && P[k] == P[l])
		{
			++k;
			++l;
		}
		next[1] = l;
		int i = 2;
		while(i < lenp)
		{
			int temp = next[i-a];
			if(i+temp < k) next[i] = temp;
			else
			{
				checkmax(k, i);
				l = k-i;
				while(k < lenp && P[k] == P[l])
				{
					++k;
					++l;
				}
				next[i] = l;
				a = i;
			}
			++i;
		}
		next[lenp] = 0;
	}
	TY T[N];
	int lent;
	int extend[N];
	void getextend()
	{
		int i, a, p, j(-1);
		for(i = 0; i < lent; ++i, --j)
		{
			if(j < 0 || i+next[i-a] >= p)
			{
				if(j < 0) j = 0, p = i;
				while(p < lent && j < lenp && T[p] == P[j]) ++p, ++j;
				extend[i] = j, a = i;
			}
			else extend[i] = next[i-a];
		}
	}
};

void rev(char *sp, int len){
	int l = 0, r = len-1;
	while(l < r){
		swap(sp[l], sp[r]);
		++l;
		--r;
	}
}

EXKMP<char, MAXN> exk;
int cnt1[MAXN], cnt2[MAXN];

int main(){
	int TC;	
	scanf("%d", &TC);
	while(TC--){
		scanf("%s%s", exk.T, exk.P);
		exk.lenp = strlen(exk.P);
		exk.lent = strlen(exk.T);
		exk.getnext();
		exk.getextend();
		memset(cnt1, 0, sizeof(cnt1[0])*(exk.lenp+1));
		for(int i = 0; i < exk.lent; ++i) ++cnt1[exk.extend[i]];
		for(int i = exk.lenp-1; i > 0; --i) cnt1[i] += cnt1[i+1];
		rev(exk.P, exk.lenp);
		rev(exk.T, exk.lent);
		exk.getnext();
		exk.getextend();
		memset(cnt2, 0, sizeof(cnt2[0])*(exk.lenp+1));
		for(int i = 0; i < exk.lent; ++i) ++cnt2[exk.extend[i]];
		for(int i = exk.lenp-1; i > 0; --i) cnt2[i] += cnt2[i+1];
		LL ans = 0;
		for(int i = 1; i < exk.lenp; ++i) ans += (LL)cnt1[i]*cnt2[exk.lenp-i];
		printf("%lld\n", ans);
	}
	return 0;
}



你可能感兴趣的:(Marlon's String zoj3587)