SPOJ1812 LCS2
book
归档:
solution
flag
浪费了我一晚上的生命…
Solution
关于本题有两种做法,我一开始写的第一种:建立广义SAM,统计parent树上的endpos集合是否可以包含所有的字符串,如果可以就用len更新ans。可以状压。
做法我拍了一下,大概是没问题的。但是这沙雕题卡常200ms我硬是给卡了一晚上😂然后发现一些神奇的问题。比如广义SAM是没法用基数排序来确定树上拓扑序的,所以得队列硬上,可惜不管怎么写都卡不过200ms。
另一种做法就是神奇的转移:先建一个串,然后对于后加入的每个串计算一下状态匹配的最大值(可以通过后缀链接上传),然后再对于每个串取个最小值,最后总体取个最大值。这样的做法基本上是常数很小的 $O(n)$ ,或者是我常数制造机了…
Code - 80ms
// Code by ajcxsu
// Problem: LCS2
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int len[N], fa[N], ch[N][26];
int lst=1, idx=1;
inline void add(int c) {
int p=lst, np=lst=++idx; len[np]=len[p]+1;
for(; p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else {
int nq=++idx; for(int i=0; i<26; i++) ch[nq][i]=ch[q][i];
fa[nq]=fa[q];
len[nq]=len[p]+1, fa[q]=fa[np]=nq;
for(; p && ch[p][c]==q; p=fa[p]) ch[p][c]=nq;
}
}
}
int qu[N], h, t;
char str[N];
int bu[N], id[N];
int su[N], f[N];
void solve() {
int x=1, l=0;
memset(su, 0, sizeof(su));
for(char *p=str; *p; p++) {
if(ch[x][*p-'a']) l++, x=ch[x][*p-'a'];
else {
while(x && !ch[x][*p-'a']) x=fa[x];
if(!x) l=0, x=1;
else l=len[x]+1, x=ch[x][*p-'a'];
}
su[x]=max(su[x], l);
}
for(int i=idx; i>=1; i--) su[fa[id[i]]]=max(su[fa[id[i]]], su[id[i]]);
for(int i=1; i<=idx; i++) len[i]=min(len[i], su[i]);
}
int main() {
scanf("%s", str);
for(char *p=str; *p; p++) add(*p-'a');
for(int i=1; i<=idx; i++) bu[len[i]]++;
for(int i=1; i<=idx; i++) bu[i]+=bu[i-1];
for(int i=idx; i>=1; i--) id[bu[len[i]]--]=i;
while(scanf("%s", str)==1) solve();
int ans=0;
for(int i=1; i<=idx; i++) ans=max(ans, len[i]);
printf("%d\n", ans);
return 0;
}
Code - TLE
// Code by ajcxsu
// Problem: LCS2
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int len[N], fa[N], ch[N][26], in[N];
int f[N], lst=1, idx=1;
inline void add(int c, int val) {
int p=lst, np=lst=++idx; len[np]=len[p]+1;
f[np]=1<<val;
for(; p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else {
int nq=++idx; for(int i=0; i<26; i++) ch[nq][i]=ch[q][i];
fa[nq]=fa[q], f[nq]=f[q];
len[nq]=len[p]+1, fa[q]=fa[np]=nq;
for(; p && ch[p][c]==q; p=fa[p]) ch[p][c]=nq;
}
}
}
int qu[N], h, t;
char str[N];
int main() {
int nidx=0;
while(scanf("%s", str)==1) {
lst=1;
for(char *p=str; *p; p++) add(*p-'a', nidx);
++nidx;
}
nidx=(1<<nidx)-1;
int ans=0, na, nf;
for(int i=1; i<=idx; i++) in[fa[i]]++;
for(int i=1; i<=idx; i++) if(!in[i]) qu[t++]=i;
while(h!=t) {
na=qu[h++], nf=fa[na];
if(f[na]==nidx && len[na]>ans) ans=len[na];
f[nf]|=f[na], in[nf]--;
if(!in[nf]) qu[t++]=nf;
}
printf("%d\n", ans);
return 0;
}
navigate_before
JZOJ6077 K君的游戏
Railway
navigate_next