• hdu5853 (后缀自动机)


    Problem Jong Hyok and String

    题目大意

      给你n个字符串,有q个询问。

      定义set(s)={(i,j)} 表示 s在第i个字符串中出现,且末尾位置为j。

      对于一个询问,求set(Qi)=set(t) ,t的数量。

      (n,q<=10^5 , 字符串总长<=10^5)

    解题分析

      直接将n个串塞进一个后缀自动机里面。

      对于一个询问串qi,找到其在后缀自动机中出现的位置j。

      则答案为len[j] - len[fail[j]] 。 (具体为什么还需要好好斟酌一下)

    参考程序

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 #define V 100008
     7 int ans[V];
     8 struct sam{
     9     int nt[V*2][26],f[V*2],a[V*2],rig[V*2];
    10     int last,sum,len;
    11     int p,q,np,nq;
    12 
    13     void clear(){
    14         memset(f,-1,sizeof(f));
    15         memset(a,0,sizeof(a));
    16         memset(nt,-1,sizeof(nt));
    17         last = sum = len=0;
    18     }
    19     void insert(int ch){
    20         len++;
    21         if (~nt[last][ch] && a[nt[last][ch]]==len){
    22             last=nt[last][ch]; return;
    23         }
    24         p=last; last=np=++sum; a[np]=a[p]+1; rig[np]=1;
    25         for (;~p && !~nt[p][ch];p=f[p]) nt[p][ch]=np;
    26         if (p==-1) f[np]=0;
    27         else
    28         {
    29             q=nt[p][ch];
    30             if (a[q]==a[p]+1) f[np]=q;
    31             else
    32             {
    33                 nq=++sum; a[nq]=a[p]+1;
    34                 memcpy(nt[nq],nt[q],sizeof(nt[q]));
    35                 f[nq]=f[q];
    36                 f[q]=f[np]=nq;
    37                 for (;~p && nt[p][ch]==q;p=f[p]) nt[p][ch]=nq;
    38             }
    39         }
    40     }
    41     int work(char *s,int l){
    42         int now=0;
    43         for (int i=1;i<=l;i++){
    44             if (nt[now][s[i]-'a']==-1) return 0;
    45             now=nt[now][s[i]-'a'];  
    46         }
    47         return a[now]-a[f[now]];
    48     }
    49 }sam;
    50 
    51 char str[V];
    52 void work(){
    53     sam.clear();
    54     int n,m;
    55     scanf("%d %d",&n,&m);
    56     for (int i=1;i<=n;i++){
    57         sam.len=sam.last=0;
    58         scanf("%s",str+1);
    59         int len=strlen(str+1);
    60         for (int j=1;j<=len;j++) sam.insert(str[j]-'a');
    61     }
    62     for (int i=1;i<=m;i++){
    63         scanf("%s",str+1);
    64         int len=strlen(str+1);
    65         printf("%d
    ",sam.work(str,len));   
    66     }
    67 }
    68 
    69 int main(){
    70     int T;
    71     scanf("%d",&T);
    72     for (int t=1;t<=T;t++){
    73         printf("Case #%d:
    ",t );
    74         work();
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    ubuntu 制做samba
    《Programming WPF》翻译 第4章 前言
    《Programming WPF》翻译 第4章 3.绑定到数据列表
    《Programming WPF》翻译 第4章 4.数据源
    《Programming WPF》翻译 第5章 6.触发器
    《Programming WPF》翻译 第4章 2.数据绑定
    《Programming WPF》翻译 第4章 1.不使用数据绑定
    《Programming WPF》翻译 第5章 7.控件模板
    《Programming WPF》翻译 第5章 8.我们进行到哪里了?
    《Programming WPF》翻译 第5章 5.数据模板和样式
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5778193.html
Copyright © 2020-2023  润新知