• [USACO17DEC]Standing Out from the Herd(广义后缀自动机)


    题意

    定义一个字符串的「独特值」为只属于该字符串的本质不同的非空子串的个数。如 "amy" 与 “tommy” 两个串,只属于 "amy" 的本质不同的子串为 "a" "am" "amy" 共 3 个。只属于 "tommy" 的本质不同的子串为 "t" "to" "tom" "tomm" "tommy" "o" "om" "omm" "ommy" "mm" "mmy" 共 11 个。 所以 "amy" 的「独特值」为 3 ,"tommy" 的「独特值」为 11 。

    给定 N ( N10^5 )  个字符集为小写英文字母的字符串,所有字符串的长度和小于 10^5 ,求出每个字符串「独特值」。

    题解

      这题和喵星人的点名那题有点像啊……会了那题做这题挺简单的

      先把所有串一起建一个广义SAM,然后把所有串放上去跑一遍,记录一下每一个子串属于多少个原串。然后再把所有串放上去跑一边,如果这个子串只属于一个原串,那么就把它的答案加上$l[i]-l[fa[i]]$(都是后缀自动机上的节点) 

     1 // luogu-judger-enable-o2
     2 //minamoto
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 char sr[1<<21],z[20];int C=-1,Z;
     7 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
     8 inline void print(int x){
     9     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    10     while(z[++Z]=x%10+48,x/=10);
    11     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    12 }
    13 const int N=1e5+5;
    14 char c[N];int len[N],tot,ans[N],s[N];
    15 int fa[N<<1],ch[N<<1][26],l[N<<1],sz[N<<1],las[N<<1];
    16 int n,cnt=1,last=1;
    17 void ins(int c){
    18     int p=last,np=++cnt;last=np,l[np]=l[p]+1;
    19     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
    20     if(!p) fa[np]=1;
    21     else{
    22         int q=ch[p][c];
    23         if(l[p]+1==l[q]) fa[np]=q;
    24         else{
    25             int nq=++cnt;l[nq]=l[p]+1;
    26             memcpy(ch[nq],ch[q],sizeof(ch[q]));
    27             fa[nq]=fa[q];fa[q]=fa[np]=nq;
    28             for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    29         }
    30     }
    31 }
    32 void update(int x,int y){
    33     for(;x&&las[x]!=y;x=fa[x])
    34     ++sz[x],las[x]=y;
    35 }
    36 void query(int x,int y){
    37     for(;x&&las[x]!=y;x=fa[x]){
    38         if(sz[x]==1) ans[y]+=l[x]-l[fa[x]];
    39         las[x]=y;
    40     }
    41 }
    42 int main(){
    43     scanf("%d",&n);
    44     for(int i=1;i<=n;++i){
    45         scanf("%s",c+1);
    46         len[i]=strlen(c+1);
    47         last=1;
    48         for(int j=1;j<=len[i];++j) s[++tot]=c[j]-'a',ins(s[tot]);
    49     }
    50     tot=0;
    51     for(int i=1;i<=n;++i)
    52     for(int j=1,x=1;j<=len[i];++j)
    53     update(x=ch[x][s[++tot]],i);
    54     for(int i=1;i<=cnt;++i) las[i]=0;
    55     tot=0;
    56     for(int i=1;i<=n;++i)
    57     for(int j=1,x=1;j<=len[i];++j)
    58     query(x=ch[x][s[++tot]],i);
    59     for(int i=1;i<=n;++i) print(ans[i]);
    60     Ot();
    61     return 0;
    62 }
  • 相关阅读:
    Palindrome Partitioning
    Minimum Path Sum
    Maximum Depth of Binary Tree
    Minimum Depth of Binary Tree
    Unique Binary Search Trees II
    Unique Binary Search Trees
    Merge Intervals
    Merge Sorted Array
    Unique Paths II
    C++ Primer Plus 笔记第九章
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9473445.html
Copyright © 2020-2023  润新知