spoj SUBLEX - Lexicographical Substring Search【SAM】
阿新 • • 發佈:2018-11-23
先求出SAM,然後考慮定義,點u是一個right集合,代表了長為dis[son]+1~dis[u]的串,然後根據有向邊轉移是新增一個字元,所以可以根據這個預處理出si[u],表示串u後加字元能有幾個本質不同子串
然後回答的時候在樹上跑一下即可
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=300005; int n,m,fa[N],ch[N][27],dis[N],si[N],con=1,cur=1,la,h[N],cnt,a[N],c[N]; char s[N]; struct qwe { int ne,to; }e[N<<2]; void add(int u,int v) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; h[u]=cnt; } void ins(int c,int id) { la=cur,dis[cur=++con]=id; int p=la; for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=cur; if(!p) fa[cur]=1; else { int q=ch[p][c]; if(dis[q]==dis[p]+1) fa[cur]=q; else { int nq=++con; dis[nq]=dis[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[q]=fa[cur]=nq; for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } } void dfs(int u) { for(int i=h[u];i;i=e[i].ne) dfs(e[i].to); for(int i=0;i<26;i++) si[u]+=si[ch[u][i]]; } int main() { scanf("%s%d",s+1,&m); n=strlen(s+1); for(int i=1;i<=n;i++) ins(s[i]-'a',i); for(int i=2;i<=con;i++) si[i]=1; // for(int i=2;i<=con;i++) // add(fa[i],i); // dfs(1); for(int i=1;i<=con;i++) c[dis[i]]++; for(int i=1;i<=n;i++) c[i]+=c[i-1]; for(int i=1;i<=con;i++) a[c[dis[i]]--]=i; for(int i=con;i;i--) for(int j=0;j<26;j++) si[a[i]]+=si[ch[a[i]][j]]; while(m--) { int k; scanf("%d",&k); for(int p=1;k;) { if(p!=1) k--; if(!k) break; for(int i=0;i<26;i++) if(ch[p][i]) { if(k>si[ch[p][i]]) k-=si[ch[p][i]]; else { printf("%c",i+'a'); p=ch[p][i]; break; } } } puts(""); } }