BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]

4698: Sdoi2008 Sandy的卡片

题意:差分后就是多个串LCS


SAM+map大法好

模板打错 智力-2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
const int N=2005;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

namespace sam{
	struct meow{map<int, int> ch; int par, val;} t[N];
	int sz=1, last=1, root=1;
void extend(int c) {
	int p=last, np=++sz; t[np].val=t[p].val+1;
	for(; p && !t[p].ch[c]; p=t[p].par) t[p].ch[c]=np;
	if(!p) t[np].par = root;
	else {
		int q = t[p].ch[c];
		if(t[q].val == t[p].val+1) t[np].par = q;
		else {
			int nq = ++sz; t[nq]=t[q]; t[nq].val=t[p].val+1;
			t[q].par = t[np].par = nq;
			for(; p && t[p].ch[c]==q; p=t[p].par) t[p].ch[c] = nq;
		}
	}
	last=np;
}
	int c[N], a[N], ans[N];
	void RadixSort() {
		for(int i=0; i<=sz; i++) c[i]=0;
		for(int i=1; i<=sz; i++) c[t[i].val]++;
		for(int i=1; i<=sz; i++) c[i] += c[i-1];
		for(int i=sz; i>=1; i--) a[ c[t[i].val]-- ]=i;
		for(int i=1; i<=sz; i++) ans[i] = t[i].val;
	}

	int f[N]; // max lenth
	void solve(int *s, int n) { //puts("
 solve");
		int u=root, now=0;
		for(int i=1; i<=n; i++) {
			int c = s[i]; //printf("i %d  %d
",i,c);
			if(t[u].ch.count(c)) u=t[u].ch[c], f[u] = max(f[u], ++now);
			else {
				while(u && !t[u].ch.count(c)) u=t[u].par;
				if(!u) u=root, now=0;
				else now=t[u].val, u=t[u].ch[c], f[u] = max(f[u], ++now);
			}
		}
		for(int i=sz; i>=1; i--) {
			int u=a[i]; ans[u] = min(ans[u], f[u]); //printf("f %d %d
",u,f[u]);
			if(f[u] && t[u].par) f[t[u].par] = t[t[u].par].val;
			f[u]=0;
		}
	}
}
int n, len, s[N], last, x;
int main() {
	freopen("in","r",stdin);
	n=read();
	len=read(); last=read();
	for(int i=1; i<len; i++) x=read(), s[i]=x-last, last=x;
	len--;
	for(int i=1; i<=len; i++) sam::extend(s[i]);
	sam::RadixSort();
	for(int i=2; i<=n; i++) {
		len=read(); last=read();
		for(int i=1; i<len; i++) x=read(), s[i]=x-last, last=x;
		len--;
		sam::solve(s, len);
	}
	int ans=0;
	for(int i=2; i<=sam::sz; i++) ans = max(ans, sam::ans[i]);
	printf("%d", ans+1);
}

原文地址:https://www.cnblogs.com/candy99/p/6675536.html