• Meteor


    每隔33年,狮子星宫的仙女们都要下凡游历一趟,她们包裹着纯白的冰鲛縠,在轩辕之光的庇护下降临人间。所以

    在凡间的人们并不能看清仙女们的真面目,只能见到若干束星光--我们称之为流星。仙女们的下凡游历需要经过狮

    子座守护神Saint Leo的允许。Saint Leo会从掌管天界出口的神那里得到一个羊皮卷,如果某个仙女的称谓包含在

    羊皮卷上,她就被允许前往人间(不同的仙女的称谓可以在文本里重叠,即他们是独立存在的)。羊皮卷上记录了

    一个很长的小写拉丁字符文本,每个仙女的称谓也是一个小写拉丁字符串。例如文本是:saintzeuscynthiathenahere那么仙女cynthia、athena就都被入选了(下划线部分包含了这两个名字),而hera就不能被选上(因为不包含

    在文本里面)。作为Saint Leo的助手,你的任务是帮Leo完成选人的这个繁琐的工作。

    Input

    第一行为一个整数n,表示文本的长度;

    第二行为一个长度为n的字符串文本;

    第三行为一个整数m,表示待选的仙女的个数;

    下接m行,第i行一个字符串,表示第i个仙女的称谓。

    n<=10^5,m<=10^5

    Output

    包含m行,若第i个仙女被选上,则第i行输出YES,否则输出NO。

    Sample Input

    25

    saintzeuscynthiathenahere

    3

    cynthia

    hera

    athena

    sol:AC自动机模板,注意下重复单词的处理。

     1 #pragma GCC optimize(2)
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 const int MAXN=1000000;
     5 struct Trie{
     6     int son[26];
     7     int cnt;
     8     int fail;
     9 }AC[MAXN];
    10 int n,m,tot=0,iidd[MAXN];
    11 bool ans[MAXN];
    12 char S[MAXN],T[MAXN];
    13 void add(char *s,int len,int id)
    14 {
    15     int now=0;
    16     for(register int i=0;i<len;i++)
    17     {
    18         if(!AC[now].son[s[i]-'a'])
    19           AC[now].son[s[i]-'a']=++tot;
    20         now=AC[now].son[s[i]-'a'];
    21     }
    22     if(AC[now].cnt)//如果当前单词之前出现过
    23       iidd[id]=AC[now].cnt; //该单词的id修改为之前出现过的单词id 
    24     else
    25       AC[now].cnt=id;//记录下当前now节点是第id各单词的结尾 
    26 }
    27 void get_fail()
    28 {
    29     queue<int> q;
    30     AC[0].fail=0;
    31     for(register int i=0;i<26;i++)
    32     {
    33         if(AC[0].son[i])
    34         {
    35             AC[AC[0].son[i]].fail=0;
    36             q.push(AC[0].son[i]);  
    37         }
    38     }
    39     while(!q.empty())
    40     {
    41         int u=q.front();
    42         q.pop();
    43         for(register int i=0;i<26;i++)
    44         {
    45             if(AC[u].son[i])//u下面的i节点存在 
    46                {
    47                 AC[AC[u].son[i]].fail=AC[AC[u].fail].son[i];
    48                 q.push(AC[u].son[i]);  
    49                }
    50             else
    51                   AC[u].son[i]=AC[AC[u].fail].son[i];
    52         }
    53     }
    54 }
    55 void AC_query(char *s,int len)
    56 {
    57     int now=0;
    58     for(register int i=0;i<len;i++)
    59     {
    60         now=AC[now].son[s[i]-'a'];
    61         for(register int t=now;t;t=AC[t].fail)
    62          {
    63             if(AC[t].cnt&&ans[AC[t].cnt]) break;
    64             ans[AC[t].cnt]=true;
    65         }
    66     }
    67 }
    68 int main(){
    69     scanf("%d",&n);
    70     scanf("%s",S);
    71     scanf("%d",&m);
    72     for(register int i=1;i<=m;i++) iidd[i]=i;
    73     for(register int i=1;i<=m;i++)
    74     {
    75         scanf("%s",T);
    76         add(T,strlen(T),i);
    77     }
    78     get_fail();
    79     AC_query(S,n);
    80     for(register int i=1;i<=m;i++){
    81         if(ans[iidd[i]]) printf("YES
    ");
    82         else printf("NO
    ");
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    程序员常用资源工具集合(建议收藏)
    程序员常用资源工具集合(建议收藏)
    16个烧光你脑细胞的悖论
    2.2_模型的选择
    2.1_Scikit-learn数据集
    Sklearn数据集与机器学习
    1.4_数据的特征选择
    1.4_特征的选择
    1.3_数据的特征预处理
    1.2_数据的特征抽取
  • 原文地址:https://www.cnblogs.com/cutepota/p/12687374.html
Copyright © 2020-2023  润新知