bzoj3413 匹配

https://www.lydsy.com/JudgeOnline/problem.php?id=3413

显然答案等于模式串si和模板串的每一个后缀的匹配长度之和。

这里忽略了匹配成功的情况,那种情况只需要额外特判一些东西。

显然可以用线段树合并维护出right集合。
按照要求查询即可。

#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#define N 330000
#define L 300000
#define M 8800000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline int read()
{
    char ch=0;
    int x=0,flag=1;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*flag;
}
char ch[N];
int root=1,size=1,last=1;
struct node{int len,pos,link,nxt[10];}s[N];
void extend(int k)
{
    int cur=++size,p=last;
    last=cur;s[cur].len=s[p].len+1;s[cur].pos=s[cur].len-1;
    while(p&&!s[p].nxt[k])s[p].nxt[k]=cur,p=s[p].link;
    if(!p){s[cur].link=root;return;}
    int q=s[p].nxt[k];
    if(s[q].len==s[p].len+1)s[cur].link=q;
    else
    {
        int clone=++size;
        s[clone]=s[q];s[clone].len=s[p].len+1;
        while(p&&s[p].nxt[k]==q)s[p].nxt[k]=clone,p=s[p].link;
        s[q].link=s[cur].link=clone;
    }
}
struct Segment_Tree
{
    #define lson lc[o]
    #define rson rc[o]
    #define mid ((l+r)>>1)
    int tot,lc[M],rc[M],sumv[M];
    int merge(int x,int y)
    {
        if(!x||!y)return x|y;
        int o=++tot;
        lson=merge(lc[x],lc[y]);
        rson=merge(rc[x],rc[y]);
        sumv[o]=sumv[lson]+sumv[rson];
        return o;
    }
    void optadd(int &o,int l,int r,int k)
    {
        if(!o)o=++tot;
        if(l==r){sumv[o]++;return;}
        if(k<=mid)optadd(lson,l,mid,k);
        else optadd(rson,mid+1,r,k);
        sumv[o]=sumv[lson]+sumv[rson];
    }
    int query(int o,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr)return sumv[o];
        int ans=0;
        if(ql<=mid)ans+=query(lson,l,mid,ql,qr);
        if(qr>mid)ans+=query(rson,mid+1,r,ql,qr);
        return ans;
    }
}T;
int f[N],rt[N];
bool cmp(int a,int b){return s[a].len>s[b].len;}
int main()
{
    int n=read();scanf("%s",ch);
    for(int i=0;i<n;i++)extend(ch[i]-'0'),T.optadd(rt[last],0,n,i);
    for(int i=1;i<=size;i++)f[i]=i;sort(f+1,f+size+1,cmp);
    for(int i=1;i<size;i++)  rt[s[f[i]].link]=T.merge(rt[s[f[i]].link],rt[f[i]]); 
    int m=read();
    for(int o=1;o<=m;o++)
    {
        scanf("%s",ch);
        int x=root,len=strlen(ch),p=inf,now=0;ll ans=0;
        for(int i=0;i<len;i++)
        {
            int k=ch[i]-'0';
            if(s[x].nxt[k])x=s[x].nxt[k],now++;
            else
            {
                while(x&&!s[x].nxt[k])x=s[x].link;
                if(!x){x=root;now=0;continue;}
                else now=s[x].len+1,x=s[x].nxt[k];
            }
        }
        if(now==len)p=s[x].pos-len+1;
        x=root;now=0;
        ans+=T.query(rt[x],0,n,0,min(n,p));
        for(int i=0;i<len-1;i++)
        {
            int k=ch[i]-'0';
            if(s[x].nxt[k])x=s[x].nxt[k],now++;
            else
            {
                while(x&&!s[x].nxt[k])x=s[x].link;
                if(!x){x=root;now=0;continue;}
                else now=s[x].len+1,x=s[x].nxt[k];
            }
            if(i+1==now)ans+=T.query(rt[x],0,n,0,min(n,p+i));
        }
        printf("%lld\n",ans);
    }
    return 0;
}

posted @ 2019-01-04 21:42  Creed-qwq  阅读(134)  评论(0编辑  收藏  举报