• SPOJ705 不同的子串


    我是萌萌的传送门

    看来我的做法也没错嘛......

    看别人的代码,写后缀数组的好像是利用SA[]和height[]什么的搞一搞,看了看表示没看懂

    看了看后缀自动机众的代码,好像是用什么np->len-np->par->len更新答案,看了看表示理解不了

    于是根据我对后缀自动机的理解强行YY了一发后缀自动机+DP的做法

    我的想法是这样的:

    后缀自动机上每条从始态到终态的路径与后缀一一对应,考虑到后缀自动机压缩了冗余状态,相同的子串在后缀自动机上走出的路径是会重合的

    不难想到每条从始态到任意一点的路径应该也和每一个不同的子串一一对应,那么我们只要求出从始态到任意一点的路径数总和就好了

    因为后缀自动机一定是DAG(废话,后缀和子串肯定是有限长的),只要跑一遍记忆化搜索就行了

    一开始跪的原因是以为开点顺序一定是拓扑序,后来才想起来由于复制节点操作的存在开点顺序不一定是拓扑序......

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=50010;
     6 void expand(int);
     7 void dfs(int);
     8 int root,last,cnt=0,val[maxn<<1]={0},par[maxn<<1]={0},go[maxn<<1][26]={{0}};
     9 bool vis[maxn<<1]={false};
    10 char s[maxn];
    11 int n,f[maxn<<1]={0};
    12 int main(){
    13     freopen("subst1.in","r",stdin);
    14     freopen("subst1.out","w",stdout);
    15     root=last=++cnt;
    16     scanf("%s",s);
    17     n=strlen(s);
    18     for(int i=0;i<n;i++)expand(s[i]-'A');
    19     dfs(root);
    20     printf("%d",f[root]-1);
    21     return 0;
    22 }
    23 void expand(int c){
    24     int p=last,np=++cnt;
    25     val[np]=val[p]+1;
    26     while(p&&!go[p][c]){
    27         go[p][c]=np;
    28         p=par[p];
    29     }
    30     if(!p)par[np]=root;
    31     else{
    32         int q=go[p][c];
    33         if(val[q]==val[p]+1)par[np]=q;
    34         else{
    35             int nq=++cnt;
    36             memcpy(go[nq],go[q],sizeof(go[q]));
    37             val[nq]=val[p]+1;
    38             par[nq]=par[q];
    39             par[q]=nq;
    40             par[np]=nq;
    41             while(p&&go[p][c]==q){
    42                 go[p][c]=nq;
    43                 p=par[p];
    44             }
    45         }
    46     }
    47     last=np;
    48 }
    49 void dfs(int x){
    50     vis[x]=true;
    51     f[x]=1;
    52     for(int c=0;c<26;c++)if(go[x][c]){
    53         if(!vis[go[x][c]])dfs(go[x][c]);
    54         f[x]+=f[go[x][c]];
    55     }
    56 }
    View Code

    然而生成魔咒那题想不到合适的做法在线维护(也许需要用到DAG的支配树?然而我不会......),还是乖乖抄了用np->len-np->par->len更新答案的做法才过的......

  • 相关阅读:
    如何正确设置数据库连接池的大小
    spring生命周期
    Spring高级进阶:BeanFactoryPostProcessor
    Spring Bean的生命周期(非常详细)
    表达式求值相关算法
    golang 命令行参数解析 hflag
    golang 标准命令行解析库 flag
    docker consul 环境搭建
    docker etcd 环境搭建
    mysql 事务
  • 原文地址:https://www.cnblogs.com/hzoier/p/6347439.html
Copyright © 2020-2023  润新知