• hdu 5129 Yong Zheng's Death(AC自动机fail树的应用)


    题目链接:hdu 5129 Yong Zheng's Death

    题意:

    给你n个串,每个串串长30,现在让你构造串,使得该串能分成uv,u和v都是给出串中的前缀。

    问能构造出多少这样的串。

    题解:

    这题主要是在如何去重。

    如果不考虑重复,显然就是不同前缀串的数量的平方。

    但是这里有算重,这里要求,以i节点为后缀的前缀个数。

    这是一个AC自动机fail树的性质,以i节点为后缀的前缀个数等于该节点的子树大小。

    然后后面做的就像这位dalao说的一样。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int AC_N=10000*51,tyn=26;
     6 struct AC_automation{
     7     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],fa[AC_N],tot;
     8     inline int getid(char x){return x-'a';}
     9     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
    10     void init(){tot=-1,fail[0]=-1,nw();}
    11     void insert(char *s,int x=0){
    12         for(int i=0,w;s[i];x=tr[x][w],i++)
    13             if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot,fa[tot]=x;
    14         cnt[x]++;//串尾标记 
    15     }
    16     void build(int head=1,int tail=0){
    17         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
    18         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
    19             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
    20             else tr[x][i]=tr[fail[x]][i];
    21     }
    22     int sum[AC_N];//以i节点为后缀的前缀个数
    23     vector<int>g[AC_N];
    24     
    25     void dfs(int x)
    26     {
    27         sum[x]=1;
    28         for(auto &it:g[x])
    29             dfs(it),sum[x]+=sum[it];
    30     }
    31     void solve()
    32     {
    33         F(i,0,tot)g[i].clear();
    34         F(i,1,tot)g[fail[i]].push_back(i);
    35         dfs(0);
    36         long long tmp=0;
    37         F(i,1,tot)if(fail[i])
    38         {
    39             int p=fail[i],q=i;
    40             while(p)p=fa[p],q=fa[q];
    41             tmp+=sum[q]-1;
    42         }
    43         printf("%lld
    ",1ll*tot*tot-tmp);
    44     }
    45 }AC;
    46 
    47 int n;
    48 char s[50];
    49 
    50 int main()
    51 {
    52     while(scanf("%d",&n),n)
    53     {
    54         AC.init();
    55         F(i,1,n)scanf("%s",s),AC.insert(s);
    56         AC.build(),AC.solve();
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    POJ-2378 Tree Cutting
    ZOJ-3870 Team Formation
    POJ-1741 Tree (树上点分治)
    POJ-3107 Godfather
    HDU-3586 Information Disturbing(树形DP+删边)
    POJ 2796 (单调栈 + 前缀和)
    POJ 3250(单调栈)
    ATCoder 116 D (思维+贪心+栈)
    POJ2528 (离散化+线段树)
    HDU 2795(思维+线段树)
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7674078.html
Copyright © 2020-2023  润新知