【SPOJ 1812】Longest Common Substring II

http://www.spoj.com/problems/LCS2/
这道题想了好久。
做法是对第一个串建后缀自动机,然后用后面的串去匹配它,并在走过的状态上记录走到这个状态时的最长距离。每匹配完一个串要对每个状态往它的parent更新,因为状态记录的最长距离一定大于parent的val值,所以parent的最长距离直接赋为val即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct State {
	State *par, *go[26];
	int val, mn, now;
} *root, *last, pool[250003], *id[250003];
int tot = 0;

State *newState(int _val) {
	State *t = &pool[++tot];
	t->par = 0; t->val = t->now = 0;
	memset(t->go, 0, sizeof(t->go));
	t->mn = t->val = _val;
	return t;
}

void extend(int w) {
	State *p = last;
	State *np = newState(p->val + 1);
	while (p && p->go[w] == 0)
		p->go[w] = np, p = p->par;
	if (p == 0) np->par = root;
	else {
		State *q = p->go[w];
		if (q->val == p->val + 1) np->par = q;
		else {
			State *nq = newState(p->val + 1);
			memcpy(nq->go, q->go, sizeof(q->go));
			nq->par = q->par;
			q->par = np->par = nq;
			while (p && p->go[w] == q)
				p->go[w] = nq, p = p->par;
		}
	}
	last = np;
}

int len, c[100003];
char s[100003];

int main() {
	root = last = newState(0);
	scanf("%s", s + 1);
	len = strlen(s + 1);
	for(int i = 1; i <= len; ++i)
		extend(s[i] - 'a');
	for(int i = 1; i <= tot; ++i)
		++c[pool[i].val];
	for(int i = 1; i <= len; ++i)
		c[i] += c[i - 1];
	for(int i = tot; i >= 1; --i)
		id[c[pool[i].val]--] = &pool[i];
	
	State *tmp; int now, x;
	while (~scanf("%s", s + 1)) {
		len = strlen(s + 1);
		tmp = root; now = 0;
		for(int i = 1; i <= len; ++i) {
			x = s[i] - 'a';
			if (tmp->go[x]) {
				tmp = tmp->go[x];
				++now;
			} else {
				while (tmp && tmp->go[x] == 0)
					tmp = tmp->par;
				if (tmp == 0) tmp = root, now = 0;
				else now = tmp->val + 1, tmp = tmp->go[x];
			}
			tmp->now = max(tmp->now, now);
		}
		for(int i = tot; i >= 1; --i) {
			tmp = id[i];
			tmp->mn = min(tmp->mn, tmp->now);
			if (tmp->par != 0 && tmp->now != 0) tmp->par->now = tmp->par->val;
			tmp->now = 0;
		}
	}
	
	int ans = 0;
	for(int i = 1; i <= tot; ++i)
		ans = max(ans, pool[i].mn);
	printf("%d\n", ans);
	return 0;
}
posted @ 2016-10-01 19:00  abclzr  阅读(655)  评论(0编辑  收藏  举报