zoukankan      html  css  js  c++  java
  • 【BZOJ】2099: [Usaco2010 Dec]Letter 恐吓信

    【题意】给定长度为n和m的两个字符串S和T,要求在字符串S中取出若干段拼成T(可重复取),求最小段数,n,m<=50000。

    【算法】后缀自动机 || 后缀数组

    【题解】对串S建SAM,然后在上面尽可能地匹配T,匹配几次得到T就是答案。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    const int maxn=100010;
    struct tree{int len,fa,t[30];}t[maxn*2];
    int tot,last,n,m,b[maxn];
    void insert(int c){
        int np=++tot;
        t[np].len=t[last].len+1;
        int x=last;
        while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
        last=np;
        if(!x)t[np].fa=1;else{
            int y=t[x].t[c];
            if(t[y].len==t[x].len+1)t[np].fa=y;else{
                int nq=++tot;
                t[nq]=t[y];
                t[nq].len=t[x].len+1;
                t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
                while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        tot=last=1;
        for(int i=1;i<=n;i++){
            char c=getchar();
            while(c<'A'||c>'Z')c=getchar();
            insert(c-'A');
        }
        for(int i=1;i<=m;i++){
            char c=getchar();
            while(c<'A'||c>'Z')c=getchar();
            b[i]=c-'A';
        }
        int len=1,ans=0;
        while(len<=m){
            int now=1;
            while(len<=m&&t[now].t[b[len]])now=t[now].t[b[len++]];
            ans++;
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    洛谷P4175 网络管理
    洛谷P2605 基站选址
    洛谷P3723 礼物
    bzoj3771 Triple
    洛谷P3321 序列统计
    bzoj2194 快速傅里叶之二
    1109课堂内容整理
    响应式网页
    表单隐藏域有什么作用?
    1106课堂笔记
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8118348.html
Copyright © 2011-2022 走看看