zoukankan      html  css  js  c++  java
  • 【AC自动机】单词

    【题目链接】

    https://loj.ac/problem/10060

    【题意】

    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

    【题解】

    与AC自动机模板题3类似,但是这个题目记录的子串是不能重叠的。

    利用下标从后往前历遍,然后把对应的位置的地方叠加到公共后缀。原因是:如果该单词出现过,那么对应的公共后缀肯定也出现过。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N = 1005;
     5 const int M = 1e6+10;
     6 char S[N][205];
     7 int Trie[M][26],fail[M],End[M],Sz[M];
     8 int Q[M],Head,Tail;
     9 int head[M],nxt[M],to[M],cnt;
    10 int n,idx=1;
    11 
    12 void Add_edge(int u,int v);
    13 void dfs(int u);
    14 void Insert( char s[] , int Id){
    15     int p = 1 ;
    16     for(int i=0;s[i];i++){
    17         int t = s[i] - 'a' ;
    18         if( !Trie[p][t] )
    19             Trie[p][t] = ++idx ;
    20         p = Trie[p][t] ;
    21         Sz[p] ++ ;
    22     }
    23     End[Id] = p ;
    24 }
    25 void Build(){
    26     Head = 1 , Tail = 0;
    27     for(int i=0;i<26;i++) Trie[0][i] = 1 ;
    28 
    29     Q[++Tail] = 1 ;
    30     while( Head <= Tail ){
    31         int u = Q[Head++];
    32         for(int i=0;i<26;i++){
    33             int To = Trie[u][i];
    34             if( To ){
    35                 fail[To] = Trie[fail[u]][i];
    36                 Q[++Tail] = To;
    37             }else{
    38                 Trie[u][i] = Trie[fail[u]][i];
    39             }
    40         }
    41     }
    42 }
    43 void Query(){
    44 
    45     /*for(int i=1,p=1;i<=n;i++){
    46         p = 1 ;
    47         for(int j=0;S[i][j];j++){
    48             int t = S[i][j] - 'a' ;
    49             p = Trie[p][t];
    50             Sz[p] ++;
    51         }
    52     }*/
    53 
    54     for(int i=idx;i>=1;i--){
    55 //        Add_edge(fail[i],i);
    56         Sz[fail[Q[i]]] += Sz[Q[i]];
    57     }
    58     //dfs(1);
    59     for(int i=1;i<=n;i++){
    60         printf("%d
    ",Sz[End[i]]);
    61     }
    62 }
    63 int main()
    64 {
    65     scanf("%d",&n);
    66     for(int i=1;i<=n;i++){
    67         scanf("%s",S[i]);
    68         Insert(S[i],i);
    69 
    70         //printf("### %s ### 
    ",S[i]);
    71     }
    72     Build();
    73     //printf("@@@@
    ");
    74     Query();
    75     return 0;
    76 }
    77 void dfs(int u){
    78     for(int i=head[u];i;i=nxt[i] ){
    79         int To = to[i] ;
    80         dfs( To ) ;
    81         Sz[u] += Sz[To] ;
    82     }
    83 }
    84 void Add_edge(int u,int v){
    85     nxt[++cnt] = head[u];
    86     head[u] = cnt ;
    87     to[cnt] = v ;
    88 }
    不重叠统计次数
  • 相关阅读:
    vue项目index.html缓存
    vue刷新当前页面
    keep-alive
    JS刷算法题:二叉树
    CSS动效集锦,视觉魔法的碰撞与融合(三)
    算法:栈和队列题目集合(一)
    浅谈设计模式(二):装饰器模式|中介模式|原型模式
    聊聊JS的二进制家族:Blob、ArrayBuffer和Buffer
    浅谈设计模式(一):状态模式|外观模式|代理模式
    纵论WebAssembly,JS在性能逆境下召唤强援
  • 原文地址:https://www.cnblogs.com/Osea/p/11366999.html
Copyright © 2011-2022 走看看