BZOJ3511:土地划分 网络流
BZOJ1822:[JSOI2010]Frozen Nova 冷冻波 二分+计算几何+网络流

BZOJ3413:匹配 后缀自动机

shinbokuow posted @ Feb 05, 2015 10:36:09 PM in BZOJ with tags 后缀自动机 , 2100 阅读

思路:

这道题真心是一道字符串好题.我要不是膜拜了秦神的代码现在还看不出个所以然...(果然太弱不解释)

 

首先呢,题目的意思其实就是让我们求询问串与原串的每一个后缀的LCP之和.但是呢,有一个Trick,那就是找到整个串之后就不找啦!

那么先考虑一种简单的情况,就是原串中并不存在询问串.

那么,我们在逆序后缀树上走,每走到一个位置,就看一下当前串出现了几次.这样,实际上每次统计的都是这一位的贡献.

现在有限制.我们可以预先处理出询问串第一次出现的位置.那么我们可以离线处理,利用dfs序来维护逆序后缀树,然后将所有询问按照限制从小到大累加贡献.

 

有点不好说.详情见代码.

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
  
typedef long long LL;
  
#define N 100010
#define M 3000010
#define Q 500010
int tranc[N<<1][10],pa[N<<1],len[N<<1],first[N<<1],ins[N],cnt,root,last;
inline int newnode(int l){
    len[++cnt]=l;return cnt;
}
  
char s[N];
  
namespace Fio{
    inline int getc(){
        static const int L=1<<15;static char buf[L],*S=buf,*T=buf;
        if(S==T){T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;}
        return*S++;
    }
    inline bool digit(char c){return c>='0'&&c<='9';}
    template<typename T>inline void Get(T&x){
        int c;while(!digit(c=getc()));x=c-'0';while(digit(c=getc()))x=(x<<1)+(x<<3)+c-'0';
    }
    char buf[500010*12],*o=buf;
    template<typename T>inline void print(T x){
        static int stk[100];int top=0;
        if(!x)*o++=48;else{for(;x;x/=10)stk[++top]=x%10;for(int i=top;i>=1;--i)*o++=48+stk[i];}
        *o++='\n';
    }
    inline void flush(){fwrite(buf,1,o-buf,stdout);}
}
using namespace Fio;
  
namespace Tree{
    int head[N<<1],next[N<<1],end[N<<1];
    inline void addedge(int a,int b){
        static int q=1;end[q]=b,next[q]=head[a],head[a]=q++;
    }
    int in[N<<1],out[N<<1],tclock;
    inline void dfs(int x){
        in[x]=++tclock;
        for(int j=head[x];j;j=next[j])dfs(end[j]);
        out[x]=tclock;
    }
    int A[N<<1];
    inline int ask(int x){int r=0;for(;x;x-=x&-x)r+=A[x];return r;}
    inline void mdf(int x,int add){for(;x<=cnt;x+=x&-x)A[x]+=add;}
    inline void addnode(int x){mdf(in[x],1);}
    inline int asksubtree(int x){return ask(out[x])-ask(in[x]-1);}
}
 
namespace Query{
    int head[N],next[M],end[M],lab[M];
    inline void insert(int a,int b,int _lab){
        static int q=1;end[q]=b,next[q]=head[a],head[a]=q,lab[q++]=_lab;
    }
}
  
LL res[Q];
char Read[100010];
  
char ch;
int main(){
    int n;Get(n);register int i,j;
      
    int id=0;while(!digit(ch=getc()));s[++id]=ch;
    while(digit(ch=getc()))s[++id]=ch;  
     
    root=last=newnode(0);
    int p,q,np,nq,y;
    for(i=1;i<=n;++i){
        ins[i]=np=newnode(len[last]+1);
        for(y=s[i]-'0',p=last;p&&!tranc[p][y];p=pa[p])tranc[p][y]=np;
        if(!p)pa[np]=root;
        else{
            q=tranc[p][y];
            if(len[q]==len[p]+1)pa[np]=q;
            else{
                nq=newnode(len[p]+1),pa[nq]=pa[q],pa[q]=pa[np]=nq;
                memcpy(tranc[nq],tranc[q],sizeof tranc[q]);
                for(;p&&tranc[p][y]==q;p=pa[p])tranc[p][y]=nq;
            }
        }last=np;
    }
      
 
    for(i=1;i<=n;++i)for(p=ins[i];p;p=pa[p])if(!first[p])first[p]=i;else break;
     
    for(i=1;i<=cnt;++i)if(pa[i])Tree::addedge(pa[i],i);
    Tree::dfs(1);
     
     
     
    int cas;Get(cas);
    for(i=1;i<=cas;++i){
        int len=0;while(!digit(ch=getc()));Read[++len]=ch;
        while(digit(ch=getc()))Read[++len]=ch;
         
        bool find=1;int p=root;
        for(j=1;j<=len;++j){
            y=Read[j]-'0';if(tranc[p][y])p=tranc[p][y];else{find=0;break;}
        }
        if(!find){
            res[i]=n;
            for(p=root,j=1;j<=len;++j){
                y=Read[j]-'0';if(tranc[p][y])p=tranc[p][y],Query::insert(n,p,i);else break;
            }
        }
        else{
            res[i]=first[p]-len;
            int firstins=first[p];
            for(p=root,j=1;j<=len;++j){
                y=Read[j]-'0',Query::insert(firstins-len+j,p=tranc[p][y],i);
            }
        }
    }
     
    for(i=1;i<=n;++i){
        Tree::addnode(ins[i]);
        for(j=Query::head[i];j;j=Query::next[j])res[Query::lab[j]]+=Tree::asksubtree(Query::end[j]);
    }
      
    for(i=1;i<=cas;++i)Fio::print(res[i]);
 
    Fio::flush();
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter