• poj3415 Common Substrings(后缀自动机)


    A substring of a string T is defined as:

     

    Tik)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|.

     

    Given two strings AB and one integer K, we define S, a set of triples (ijk):

     

    S = {( ijk) | k≥ KAik)= Bjk)}.

     

    You are to give the value of |S| for specific AB and K.

    Input

    The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.

    1 ≤ |A|, |B| ≤ 105
    1 ≤ K ≤ min{|A|, |B|}
    Characters of A and B are all Latin letters.

     

    Output

    For each case, output an integer |S|.

    Sample Input

    2
    aababaa
    abaabaa
    1
    xx
    xx
    0
    

    Sample Output

    22
    5








    对第一个串建立自动机,然后让第二个串在上面跑,记录一下到每个状态时的匹配的长度,
    一个状态是很多后缀串的集合,我们只需要当前状态中大于等于K 小于等于匹配长度的串
    然后如果fa有长度也大于等于k的串的话,那也可以去
    为了避免每次都要向上找fa,打一个lazy标记一波,最后在一遍更新就行了。



     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ri register int
     6 using namespace std;
     7 const int N=2e5+5;
     8 typedef long long ll;
     9 int k,n;
    10 char s[N];
    11 inline int calc(char c){return c>='a'&&c<='z'?c-'a':c-'A'+26;}
    12 struct SAM{
    13     int tot,rt,last,len[N],link[N],son[N][60],siz[N],lz[N],cnt[N],rk[N];
    14     inline void init(){
    15         memset(len,0,sizeof(len)),memset(siz,0,sizeof(siz)),memset(rk,0,sizeof(rk)),memset(son,0,sizeof(son));
    16         memset(link,0,sizeof(link)),memset(cnt,0,sizeof(cnt)),memset(lz,0,sizeof(lz)),tot=last=rt=1,len[0]=-1;
    17     }
    18     inline void expend(int x){
    19         int p=last,np=++tot;
    20         siz[last=np]=1,len[np]=len[p]+1;
    21         while(p&&!son[p][x])son[p][x]=np,p=link[p];
    22         if(!p){link[np]=rt;return;}
    23         int q=son[p][x],nq;
    24         if(len[q]==len[p]+1){link[np]=q;return;}
    25         len[nq=++tot]=len[p]+1,memcpy(son[nq],son[q],sizeof(son[q])),link[nq]=link[q];
    26         while(p&&son[p][x]==q)son[p][x]=nq,p=link[p];
    27         link[q]=link[np]=nq;
    28     }
    29     inline void topsort(){
    30         for(ri i=1;i<=tot;++i)++cnt[len[i]];
    31         for(ri i=1;i<=last;++i)cnt[i]+=cnt[i-1];
    32         for(ri i=1;i<=tot;++i)rk[cnt[len[i]]--]=i;
    33         for(ri i=tot;i;--i)siz[link[rk[i]]]+=siz[rk[i]];
    34     }
    35     inline void query(){
    36         topsort();
    37         int p=1,nowlen=0;
    38         ll ans=0;
    39         for(ri i=1;i<=n;++i){
    40             int x=calc(s[i]);
    41             if(son[p][x])p=son[p][x],++nowlen;
    42             else{
    43                 while(p&&!son[p][x])p=link[p];
    44                 if(!p)p=1,nowlen=0;
    45                 else nowlen=len[p]+1,p=son[p][x];
    46             }
    47             if(nowlen>=k){
    48                 ans+=(ll)(nowlen-max(k,len[link[p]]+1)+1)*siz[p];
    49                 if(len[link[p]]>=k)++lz[link[p]];
    50             }
    51         }
    52         for(ri i=tot;i;--i){
    53             p=rk[i];
    54             ans+=(ll)lz[p]*siz[p]*(len[p]-max(k,len[link[p]]+1)+1);
    55             if(len[link[p]]>=k)lz[link[p]]+=lz[p];
    56         }
    57         cout<<ans<<'
    ';
    58     }
    59 }sam;
    60 int main(){
    61     while(scanf("%d",&k),k){
    62         scanf("%s",s+1),n=strlen(s+1),sam.init();
    63         for(ri i=1;i<=n;++i)sam.expend(calc(s[i]));
    64         scanf("%s",s+1),n=strlen(s+1),sam.query();
    65     }
    66     return 0;
    67 }







  • 相关阅读:
    第五次作业——词法分析程序的设计与实现
    第四次作业——文法和语言总结与梳理
    第三次作业-语法树,短语,直接短语,句柄
    消除左递归
    DFA最小化
    非确定的自动机NFA确定化为DFA
    正规式到正规文法与自动机
    正规文法与正规式
    词法分析程序的设计与实现
    第四次作业-文法和语言总结与梳理
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10886323.html
Copyright © 2020-2023  润新知