题意:求多个串得最长公共子序列 (字符集合无限)
思路1:广义后缀自动机
#include <bits/stdc++.h>
using namespace std;
const int maxn =1000005;
int vis[maxn<<1],tim,cnt[maxn<<1];
struct SAM{
int fa[maxn<<1], // 后缀链接
//ch[maxn<<1][ch_size],
len[maxn<<1], //该节点最长串的长度
tot, // 节点总数
last; // 代表当前的整个串
map<int,int> ma[maxn<<1];
void init(){
tot = last = 0;
fa[0] = -1;
len[0] = 0;
ma[0].clear();
}
void extend( int x ){
int p = last;
if( ma[p].find(x) != ma[p].end() ){
int q = ma[p][x];
if( len[q] == len[p]+1 ) last = q;
else{
int clone = ++tot;
len[clone] = len[p] + 1;
last = clone;
ma[clone] = ma[q];
fa[clone] = fa[q];
fa[q] = clone;
while (p != -1) {
if (ma[p].find(x) != ma[p].end() && ma[p][x] == q)ma[p][x] = clone;
else break;
p = fa[p];
}
}
return;
}
int cur = ++tot;
ma[cur].clear();
len[cur] = len[last]+1;
while( p != -1 && ma[p].find(x)==ma[p].end() ){
ma[p][x] = cur;
p = fa[p];
}
if( p == -1 ){
fa[cur] = 0;
}else {
int q = ma[p][x];
if (len[q] == len[p] + 1) {
fa[cur] = q;
} else {
int clone = ++tot;
len[clone] = len[p] + 1;
ma[clone] = ma[q];
fa[clone] = fa[q];
fa[q] = fa[cur] = clone;
while (p != -1) {
if ( ma[p].find(x) != ma[p].end() && ma[p][x] == q)ma[p][x] = clone;
else break;
p = fa[p];
}
}
}
last = cur;
}
}g;
vector<int> ve[1005];
int main(){
g.init();
int n,m;
scanf("%d",&n);
for( int i = 1;i <= n;i++ ){
scanf("%d",&m);
g.last = 0;
int pre;
scanf("%d",&pre);
for( int x,j = 2; j <= m;j++ ){
scanf("%d",&x);
ve[i].push_back( x-pre );
g.extend(x-pre);
pre = x;
}
}
for( int i = 1;i <= n;i++ ){
tim++;
int p = 0;
for( int j = 0;j < ve[i].size();j++ ){
int c = ve[i][j];
p = g.ma[p][c];
int k = p;
while( k && vis[k] != tim ){
vis[k] = tim;
cnt[k]++;
k = g.fa[k];
}
}
}
int ans = 1;
for( int i = 1;i <= g.tot;i++ ){
if( cnt[i]==n ){
ans = max( ans,g.len[i]+1 );
}
}
printf("%d\n",ans);
return 0;
}