• [coci2012]覆盖字符串 AC自动机


    给出一个长度为N的小写字母串,现在Mirko有M个若干长度为Li字符串。现在Mirko要用这M个字符串去覆盖给出的那个字符串的。覆盖时,必须保证:
    1.Mirko的字符串不能拆开,旋转;
    2.Mirko的字符串必须和给出的字符串的某一连续段完全一致才能覆盖,
    3.若干次覆盖可以部分重叠
    4.Mirko的字符串可以无限使用。
    求给出的字符串当中,有多少个字母是无法覆盖的。

    小朋友们,作为一名长者,我认为我有必要向你们传授一些人生的经验~;

    字符串的一堆函数,慎用慎用;

    本人只因没有仔细认真,把strlen(s),strlen(ch)之类的函数写在了循环的里面,造成了无限TLE的惨剧;

    图如下:

    两个strlen在里面的时候:

    #01: Accepted (15ms, 322696KB)
    #02: Accepted (15ms, 322696KB)
    #03: Accepted (187ms, 322696KB)
    #04: Accepted (3234ms, 322696KB)
    #05: Accepted (3453ms, 322624KB)
    #06: Time Limit Exceeded (?, 322624KB)
    #07: Time Limit Exceeded (?, 322624KB)
    #08: Time Limit Exceeded (?, 322624KB)
    #09: Time Limit Exceeded (?, 322624KB)
    #10: Time Limit Exceeded (?, 322624KB)
    #11: Time Limit Exceeded (?, 322624KB)
    #12: Wrong Answer (5000ms, 322624KB)
    #13: Wrong Answer (5000ms, 322624KB)
    #14: Time Limit Exceeded (?, 322624KB)
    #15: Time Limit Exceeded (?, 322624KB)
    #16: Time Limit Exceeded (?, 322624KB)
    #17: Wrong Answer (5000ms, 322624KB)
    #18: Wrong Answer (5000ms, 322624KB)
    #19: Time Limit Exceeded (?, 322624KB)

    不知道的会以为我暴力枚举;

    一个strlen在循环里的时候:

    #01: Accepted (15ms, 345056KB)
    #02: Accepted (0ms, 345056KB)
    #03: Accepted (0ms, 345056KB)
    #04: Accepted (218ms, 345056KB)
    #05: Accepted (78ms, 345056KB)
    #06: Accepted (93ms, 345056KB)
    #07: Accepted (46ms, 345056KB)
    #08: Accepted (1656ms, 345056KB)
    #09: Time Limit Exceeded (?, 345056KB)
    #10: Accepted (93ms, 344984KB)
    #11: Accepted (125ms, 344984KB)
    #12: Accepted (1562ms, 344984KB)
    #13: Time Limit Exceeded (?, 344984KB)
    #14: Accepted (171ms, 344984KB)
    #15: Accepted (500ms, 344984KB)
    #16: Accepted (1640ms, 344984KB)
    #17: Wrong Answer (5000ms, 344984KB)
    #18: Accepted (250ms, 344984KB)
    #19: Accepted (734ms, 344984KB)

    还是有三组超了;

    没有strlen在里面的时候:

    #01: Accepted (0ms, 357712KB)
    #02: Accepted (0ms, 357712KB)
    #03: Accepted (15ms, 357712KB)
    #04: Accepted (78ms, 357712KB)
    #05: Accepted (93ms, 357712KB)
    #06: Accepted (46ms, 357712KB)
    #07: Accepted (46ms, 357712KB)
    #08: Accepted (375ms, 357712KB)
    #09: Accepted (187ms, 357712KB)
    #10: Accepted (93ms, 357712KB)
    #11: Accepted (31ms, 357712KB)
    #12: Accepted (359ms, 357712KB)
    #13: Accepted (328ms, 357712KB)
    #14: Accepted (187ms, 357712KB)
    #15: Accepted (125ms, 357712KB)
    #16: Accepted (359ms, 357712KB)
    #17: Accepted (468ms, 357712KB)
    #18: Accepted (281ms, 357712KB)
    #19: Accepted (140ms, 357712KB)

    敲完这道题,我热泪盈眶啊;

    同时,我通过这道题敲了好几遍AC自动机模板;

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cstdlib>
     6 #include<ctime>
     7 #include<vector>
     8 #include<algorithm>
     9 #include<queue>
    10 #include<map>
    11 using namespace std;
    12 #define LL long long
    13 const int maxn=2500010;
    14 int n,m;
    15 char s[303000],ch[5050];
    16 bool vis[27][27][27][27][27];
    17 int linkk[1000000][27],flag[maxn],f[maxn],q[maxn],g[maxn],k[maxn],tail=0,head=1,len=0,next[maxn];
    18 void insert(){
    19     int now=0,p=strlen(ch);
    20     for(int i=0;i<p;i++){
    21         if(!linkk[now][ch[i]])linkk[now][ch[i]]=++len,g[len]=ch[i];
    22         now=linkk[now][ch[i]];
    23         if(i==p-1)flag[now]=p;
    24     }
    25 }
    26 void init(){
    27     //printf("first:%d
    ",clock());
    28     scanf("%d%s%d",&n,s,&m);
    29     for(int i=0;i<n;i++)s[i]=s[i]-'a'+1;
    30     for(int i=4;i<n;i++)vis[s[i-4]][s[i-3]][s[i-2]][s[i-1]][s[i]]=1;
    31     //printf("second:%d
    ",clock());
    32     for(int i=1;i<=m;i++){
    33         scanf("%s",ch);
    34         bool p=0;
    35         int u=strlen(ch);
    36         for(int j=0;j<u;j++)ch[j]=ch[j]-'a'+1;
    37         for(int j=4;j<u;j++)
    38             if(!vis[ch[j-4]][ch[j-3]][ch[j-2]][ch[j-1]][ch[j]]){p=1;break;}
    39         if(!p)insert();
    40     }
    41     //printf("init:%d
    ",clock());
    42 }
    43 void bfs(){
    44     head=0,tail=0;q[++tail]=0;int x=0,now=0,temp;
    45     while(++head<=tail){
    46         x=q[head];
    47         for(int i=1;i<=26;i++){
    48             if(linkk[x][i]){
    49                 now=linkk[x][i],temp=f[x];
    50                 if(x){
    51                     while(temp&&!linkk[temp][i])temp=f[temp];
    52                     f[now]=linkk[temp][i];
    53                     if(flag[f[now]])next[now]=f[now];
    54                     else next[now]=next[f[now]];
    55                 }
    56                 q[++tail]=now;
    57             }
    58         }
    59     }
    60 }
    61 void work(){
    62     bfs();
    63     //printf("bfs:%d
    ",clock());
    64     int now=0;
    65     for(int i=0;i<n;i++){
    66         if(!linkk[now][s[i]]){
    67             int temp=f[now];
    68             while(!linkk[temp][s[i]]&&temp)temp=f[temp];
    69             now=linkk[temp][s[i]];
    70         }
    71         else now=linkk[now][s[i]];
    72         int temp=now;
    73         while(temp){
    74             if(flag[temp])k[i-flag[temp]+1]=flag[temp];
    75             temp=next[temp];
    76         }
    77     }
    78     //printf("work:%d
    ",clock());
    79     int last=-1,sum=0;
    80     for(int i=0;i<n;i++){
    81         if(k[i])last=max(last,k[i]+i-1);
    82         if(i>last)sum++;
    83     }
    84     cout<<sum<<endl;
    85     //cout<<clock()<<endl;
    86 }
    87 int main(){
    88     freopen("1.in","r",stdin);
    89     freopen("1.out","w",stdout);
    90     init();
    91     work();
    92 }
    View Code
  • 相关阅读:
    python之isinstance和issubclass
    python中类的继承
    python中面向对象
    python中常用的内置模块
    Python常用模块
    python中的常用内置模块
    python中的包、模块及导入
    python中的内置函数(二)
    国内7大核心期刊
    PS学习列表
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5877408.html
Copyright © 2020-2023  润新知