• COJ 1287 求匹配串在模式串中出现的次数


    这里要在后缀自动机的节点中维护一个从到达当前位置出现的字符串总个数

    这里新添加进来的节点的状态出现的次数必然为1

    另外包含所能达到这个节点所能到达的状态一定是将它作为父亲的点

    那么说明将它作为父亲的点添加进来一定会使它的所有父亲状态数都+1

    所以直接在添加节点结束后不断向上更新

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 
     5 using namespace std;
     6 #define N 200010
     7 #define M 26
     8 
     9 struct SamNode{
    10     SamNode *son[26] , *f;
    11     int l , sc;
    12     void init(){
    13         f = NULL;
    14         for(int i=0 ; i<26 ; i++) son[i] = NULL;
    15         l = sc = 0;
    16     }
    17 }*root , *last , sam[N];
    18 
    19 int cnt , n , m , k , ret;
    20 char s[N];
    21 
    22 void init(){
    23     sam[0].init();
    24     root = last = &sam[cnt=0];
    25     ret = 0;
    26 }
    27 
    28 void add(int x)
    29 {
    30     SamNode *p = &sam[++cnt] , *jp=last;
    31     p->init();
    32     p->l = jp->l+1;
    33     p->sc=1;
    34     last = p;
    35     for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p;
    36     if(!jp) p->f = root;
    37     else{
    38         if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x];
    39         else{
    40             SamNode *r = &sam[++cnt] , *q = jp->son[x];
    41             r->init();
    42             *r = *q;
    43             r->l = jp->l+1;
    44             q->f = p->f = r;
    45             for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
    46         }
    47     }
    48     p = last;
    49     while(p->f){
    50         p = p->f;
    51         p->sc++;
    52     }
    53 }
    54 char str[55];
    55 int solve()
    56 {
    57     SamNode *cur = root;
    58     int len = strlen(str);
    59     for(int i=0 ; i<len ; i++){
    60         int v = str[i]-'a';
    61         if(cur->son[v]){
    62             cur = cur->son[v];
    63         }
    64         else{
    65             return 0;
    66         }
    67     }
    68     return cur->sc;
    69 }
    70 
    71 
    72 int main()
    73 {
    74    // freopen("data_in.txt" , "r" , stdin);
    75     int n , m , op;
    76     while(~scanf("%d%d" , &n , &m))
    77     {
    78         scanf("%s" , s);
    79 
    80         init();
    81         for(int i=0 ; i<n ; i++) add(s[i]-'a');
    82         while(m--){
    83            // cout<<m<<endl;
    84             scanf("%d" , &op);
    85             if(op==2){
    86               //  cout<<"in"<<endl;
    87                 scanf("%s" , str);
    88                 printf("%d
    " , solve());
    89 
    90             }
    91             else{
    92                 scanf("%s" , str);
    93                 add(str[0]-'a');
    94             }
    95         }
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】
    bzoj 3270: 博物馆【dp+高斯消元】
    bzoj 3105: [cqoi2013]新Nim游戏【线性基+贪心】
    bzoj 1923: [Sdoi2010]外星千足虫【高斯消元】
    bzoj 3629: [JLOI2014]聪明的燕姿【线性筛+dfs】
    bzoj 1296: [SCOI2009]粉刷匠【dp+背包dp】
    bzoj 3329: Xorequ【数位dp+矩阵乘法】
    bzoj 1306: [CQOI2009]match循环赛【dfs+剪枝】
    bzoj 4720: [Noip2016]换教室【期望dp】
    bzoj 2257: [Jsoi2009]瓶子和燃料【裴蜀定理+gcd】
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4734537.html
Copyright © 2020-2023  润新知