• luogu4770 [NOI2018]你的名字 (SAM+主席树)


    对S建SAM,拿着T在上面跑

    跑的时候不仅无法转移要跳parent,转移过去不在范围内也要跳parent(注意因为范围和长度有关,跳的时候应该把长度一点一点地缩)

    这样就能得到对于T的每个前缀,它最长的不合法的后缀的长度ill[i]

    得到他要去重,以后可以再对T建SAM,然后对于每个节点,$ans+=max(0,len[i]-max(len[fa[i]],ill[pos[i]]))$,其中pos[i]是它的right集合中随便一个位置(因为每个位置的小于len的ill都一样)

    那么怎么判在不在范围内呢..似乎可以线段树合并,带个log地求出每个节点的right

    当然也可以直接dfs序然后建主席树

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 #define MP make_pair
      5 using namespace std;
      6 typedef long long ll;
      7 const int maxn=1e6+10;
      8 
      9 inline char gc(){
     10     return getchar();
     11     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
     12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
     13 }
     14 inline ll rd(){
     15     ll x=0;char c=gc();bool neg=0;
     16     while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
     17     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
     18     return neg?(~x+1):x;
     19 }
     20 
     21 struct SAM{
     22     int len[maxn*2],fa[maxn*2],tr[maxn*2][26],pct,lst,pos[maxn*2];
     23     
     24     inline void clear(){
     25         while(pct){
     26             CLR(tr[pct],0);
     27             len[pct]=fa[pct]=pos[pct]=0;
     28             pct--;
     29         }pct=lst=1;
     30     }
     31     
     32     inline void insert(int x,bool b){
     33         int p=++pct;
     34         len[p]=len[lst]+1;pos[p]=len[p];
     35         int o=lst;lst=p;
     36         for(;o&&!tr[o][x];o=fa[o]) tr[o][x]=p;
     37         if(!o){fa[p]=1;return;}
     38         int q=tr[o][x];
     39         if(len[q]==len[o]+1){fa[p]=q;return;}
     40         int qq=++pct;if(b) pos[qq]=pos[p];
     41         len[qq]=len[o]+1;fa[qq]=fa[q];
     42         memcpy(tr[qq],tr[q],sizeof(tr[q]));
     43         fa[q]=fa[p]=qq;
     44         for(;o&&tr[o][x]==q;o=fa[o]) tr[o][x]=qq;
     45     }
     46 }S,T;
     47 
     48 char s[maxn];
     49 int N,M,Q;
     50 int ill[maxn];
     51 int cnt[maxn],rnk[maxn],dfn[maxn][2],id[maxn],tot;
     52 vector<int> eg[maxn];
     53 
     54 inline void dfs(int x){
     55     id[++tot]=x;dfn[x][0]=tot;
     56     for(int i=0;i<eg[x].size();i++) dfs(eg[x][i]);
     57     dfn[x][1]=tot;
     58 }
     59 
     60 int rt[maxn],num[maxn*20],ch[maxn*20][2],pct;
     61 
     62 inline void insert(int pre,int &p,int l,int r,int x,int y){
     63     p=++pct;num[p]=num[pre]+y;
     64     if(l<r){
     65         int m=l+r>>1;
     66         if(x<=m) insert(ch[pre][0],ch[p][0],l,m,x,y),ch[p][1]=ch[pre][1];
     67         else insert(ch[pre][1],ch[p][1],m+1,r,x,y),ch[p][0]=ch[pre][0];
     68     }
     69 }
     70 
     71 inline int query(int pre,int p,int l,int r,int x,int y){
     72     if(x>y) return 0;
     73     if(x<=l&&r<=y) return num[p]-num[pre];
     74     int m=l+r>>1,re=0;
     75     if(x<=m) re=query(ch[pre][0],ch[p][0],l,m,x,y);
     76     if(y>=m+1) re+=query(ch[pre][1],ch[p][1],m+1,r,x,y);
     77     return re;
     78 }
     79 
     80 int main(){
     81     //freopen("","r",stdin);
     82     int i,j,k;
     83     scanf("%s",s+1);N=strlen(s+1);
     84     S.clear();
     85     for(i=1;i<=N;i++) S.insert(s[i]-'a',0);
     86         
     87     for(i=2;i<=S.pct;i++) eg[S.fa[i]].push_back(i);
     88     dfs(1);
     89     for(i=1;i<=tot;i++){
     90         if(S.pos[id[i]]) insert(rt[i-1],rt[i],1,N,S.pos[id[i]],1);
     91         else rt[i]=rt[i-1]; 
     92     }
     93         
     94     Q=rd();
     95     for(i=1;i<=Q;i++){
     96         scanf("%s",s+1);M=strlen(s+1);
     97         int l=rd(),r=rd();
     98         int now=1,nl=0;
     99         for(j=1;j<=M;j++){
    100             int x=s[j]-'a';
    101             while(now&&!(S.tr[now][x]&&query(rt[dfn[S.tr[now][x]][0]-1],rt[dfn[S.tr[now][x]][1]],1,N,l+nl,r))){
    102                 if(!nl){now=0;break;}
    103                 nl--;
    104                 if(nl==S.len[S.fa[now]]) now=S.fa[now];
    105             }
    106             if(now) nl++,now=S.tr[now][x];
    107             else now=1; 
    108             ill[j]=nl;
    109             // printf("~%d %d
    ",j,ill[j]);
    110         }
    111         T.clear();
    112         for(j=1;j<=M;j++) T.insert(s[j]-'a',1);
    113         ll ans=0;
    114         for(j=2;j<=T.pct;j++){
    115             ans+=max(0,T.len[j]-max(T.len[T.fa[j]],ill[T.pos[j]]));
    116         }
    117         printf("%lld
    ",ans);
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    数据包发送
    linux 进程调度3
    linux 进程调度2
    linux 进程调度1
    进程间通信:信号
    fork vfork clone学习
    跳表
    【转】Linux内存管理综述
    如何优雅的写出链表代码
    This function or variable may be unsafe Consider using xxx instead
  • 原文地址:https://www.cnblogs.com/Ressed/p/10205523.html
Copyright © 2020-2023  润新知