BZOJ3881 [Coci2015]Divljak

字符串题!

考虑严格匹配的话肯定就是ACA辣

发现求的其实就是Fail树上的子树和

具体加一个串的话是Fail树上树链的并

那么就套板子辣

vector用unique不会自动resize的...我是憨憨= =

而unique以后后面是乱序就导致了WA...

(沃日不对啊我是多项式选手我怎么到处写数据结构)

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 2000010
#define lowbit(x) (x&-x)
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct bit
{
    int t[N],n=N-8;
    void add(int x,int v){while(x<=n) t[x]+=v,x+=lowbit(x);}
    int query(int x){int v=0; while(x) v+=t[x],x-=lowbit(x); return v;}
    int ask(int l,int r){return query(r)-query(l-1);}
}b; //bit
int ch[N][26],fail[N],tag[N],rt=1,poi=1; // ACA
struct edge{int to,lt;}e[N];
int in[N],cnt,dfn[N],idfn[N],tms,fa[N][21],sz[N],dep[N]; // fail
//----------fail-----------
void add(int x,int y){fail[y]=x; e[++cnt].to=y; e[cnt].lt=in[x]; in[x]=cnt;}
void dfs(int x)
{
    sz[x]=1; dfn[x]=++tms; idfn[tms]=x;
    for(int i=1;i<20;i++)    fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=in[x];i;i=e[i].lt)
    {
        int y=e[i].to; dep[y]=dep[x]+1;
        fa[y][0]=x; dfs(y); sz[x]+=sz[y];
    }
}
int LCA(int x,int y)
{
    if(dep[x]<dep[y])    swap(x,y);
    int len=dep[x]-dep[y];
    for(int i=0;i<20;i++)    if(len>>i&1)
        x=fa[x][i];
    if(x==y)    return x;
    for(int i=19;~i;i--)    if(fa[x][i]!=fa[y][i])
        x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
//-------------ACA------------
void insert(char c[],int n,int id)
{
    int pos=rt;
    for(int i=1;i<=n;i++)
    {
        int son=c[i]-'a';
        if(!ch[pos][son])    ch[pos][son]=++poi;
        pos=ch[pos][son];
    }
    tag[id]=pos;
}
#include<queue>
queue<int> q;
void build()
{
    for(int i=0;i<26;i++)    if(ch[rt][i])
        add(rt,ch[rt][i]),q.push(ch[rt][i]);
        else    ch[rt][i]=rt;
    while(!q.empty())
    {
        int pos=q.front(); q.pop();
        for(int i=0;i<26;i++)
            if(ch[pos][i])
                add(ch[fail[pos]][i],ch[pos][i]),q.push(ch[pos][i]);
            else
                ch[pos][i]=ch[fail[pos]][i];
    }
}
//---------insert----------
#include<vector>
#define pb push_back
vector<int> vec;
void match(char c[],int n)
{
    int pos=rt; vec.clear();
    for(int i=1;i<=n;i++)
        pos=ch[pos][c[i]-'a'],vec.pb(dfn[pos]);
    sort(vec.begin(),vec.end());
    //vec.erase(unique(vec.begin(),vec.end()),vec.end());
}
char w[N];
void solve()
{
    scanf("%s",w+1); int len=strlen(w+1); match(w,len);
    for(int i=0;i<vec.size();i++)
    {
        b.add(vec[i],1);
        if(i)    b.add(dfn[LCA(idfn[vec[i]],idfn[vec[i-1]])],-1);
    }
}
//----------query-----------
int query(int id)
{
    int pos=tag[id]; return b.ask(dfn[pos],dfn[pos]+sz[pos]-1);
}
//---------main----------
int main()
{
    int n=read();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",w+1);
        int len=strlen(w+1);
        insert(w,len,i);
    }
    build(); dfs(1);
    int q=read();
    while(q--)
    {
        int opt=read(),id;
        if(opt==1)    solve();
        else    id=read(),printf("%d\n",query(id));
    }
    return 0;
}
View Code

 

posted @ 2019-10-10 16:15  寒雨微凝  阅读(207)  评论(0编辑  收藏  举报