Spoj8093 Sevenk Love Oimaster

题目描述

题解:

对于所有n串建广义后缀自动机。

(广义后缀自动机唯一区别就是每次将las附成1,并不需要在插入时特判)

建完后再建出parent树,然后用dfs序+树状数组搞区间不同种类。

其实就是HH的项链+广义后缀自动机。很水的。(虽然我调了半个晚上)

代码:

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
int n,q;
char s[360050];
int ic(char c)
{
    if(c>='a'&&c<='z')return c-'a'+1;
    if(c>='A'&&c<='Z')return c-'A'+27;
    if(c>='0'&&c<='9')return c-'0'+53;
    if(c==',')return 63;
    if(c=='.')return 64;
    return 65;
}
int tin[2*N],tout[2*N],tim,pla[2*N];
struct SAM
{
    struct node
    {
        int len,pre,trs[68];
        vector<int>v;
    }p[2*N];
    int tot,las;
    SAM(){tot=las=1;}
    void res(){las=1;}
    void insert(int c,int k)
    {
        int np,nq,lp,lq;
        np = ++tot;
        p[np].len = p[las].len+1;
        for(lp=las;lp&&!p[lp].trs[c];lp=p[lp].pre)
            p[lp].trs[c]=np;
        if(!lp)p[np].pre = 1;
        else
        {
            lq = p[lp].trs[c];
            if(p[lq].len == p[lp].len+1)p[np].pre = lq;
            else
            {
                nq = ++tot;
                p[nq] = p[lq];
                p[nq].len = p[lp].len+1;
                p[lq].pre = p[np].pre = nq;
                while(p[lp].trs[c]==lq)
                {
                    p[lp].trs[c]=nq;
                    lp=p[lp].pre;
                }
            }
        }
        las = np;
        p[las].v.push_back(k);
    }
    int hed[2*N],cnt;
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void dfs(int u)
    {
        tin[u]=++tim;pla[tim]=u;
        for(int j=hed[u];j;j=e[j].nxt)dfs(e[j].to);
        tout[u]=tim;
    }
    void build()
    {
        for(int i=2;i<=tot;i++)
            ae(p[i].pre,i);
        dfs(1);
    }
}sam;
int ans[60050],ct;
struct Pair
{
    int l,r,id;
}qu[60050];
bool cmp(Pair a,Pair b)
{
    return a.r<b.r;
}
int f[2*N];
void up(int x,int d)
{
    if(!x)return ;
    while(x<=200000)f[x]+=d,x+=(x&(-x));
}
int down(int x)
{
    if(!x)return 0;
    int ret = 0;
    while(x)ret+=f[x],x-=(x&(-x));
    return ret;
}
int las[10050];
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        int len = strlen(s+1);
        sam.res();
        for(int j=1;j<=len;j++)
            sam.insert(ic(s[j]),i);
    }
    sam.build();
    for(int i=1;i<=q;i++)
    {
        scanf("%s",s+1);
        int len = strlen(s+1);
        int u = 1;
        for(int j=1;j<=len&&u;j++)
            u=sam.p[u].trs[ic(s[j])];
        if(u)
        {
            ct++;
            qu[ct].l = tin[u];
            qu[ct].r = tout[u];
            qu[ct].id = i;
        }
    }
    sort(qu+1,qu+1+ct,cmp);
    for(int k=1,i=1;i<=tim;i++)
    {
        for(int j=0;j<sam.p[pla[i]].v.size();j++)
        {
            up(i,1);
            up(las[sam.p[pla[i]].v[j]],-1);
            las[sam.p[pla[i]].v[j]]=i;
        }
        int tmp = down(i);
        for(;qu[k].r==i;k++)
            ans[qu[k].id] = tmp - down(qu[k].l-1);
    }
    for(int i=1;i<=q;i++)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10099155.html