• HDU-4416 Good Article Good sentence 后缀自动机


    HDU-4416 Good Article Good sentence

    题意

    给一个字符串(A)(n)个字符串(B_1,B_2,dots,B_n),问有多少个不同的字符串是(A)的子串且不是任意一个(B_i)的子串。

    (|A|le 10^5,sum|B_i|le 10^5)

    分析

    (A)(sam),每个(B_i)(sam)上跑,对于(B_i)的每个前缀在(sam)上去匹配一个最长后缀,设当前匹配到的状态为(u),将这时的最大长度记录下来为(mx[u]),那么对于这个状态中只有长度在([mx[u]+1,len[u]])这个范围内的才对答案有贡献,并且这个(mx[u])可以更新它的父节点(mx[fa[u]]=max(mx[fa[u],mx[u]])),最后扫一遍所有状态统计一下答案(ans+=len[u]-max(mx[u],len[fa[u]]))

    Code

    #include<bits/stdc++.h>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=2e5+10;
    const int inf=1e9;
    int T,n,m;
    char s[N];
    ll ans;
    vector<int>g[N];
    struct SAM{
        int last,cnt;int ch[N][26],fa[N],len[N],mx[N];
        int newnode(){
            ++cnt;
            mx[cnt]=0;
            for(int i=0;i<26;i++) ch[cnt][i]=0;
            return cnt;
        }
        void insert(int c){
            int p=last,np=newnode();last=np;len[np]=len[p]+1;
            for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
            if(!p) fa[np]=1;
            else {
                int q=ch[p][c];
                if(len[q]==len[p]+1) fa[np]=q;
                else  {
                    int nq=newnode();len[nq]=len[p]+1;
                    memcpy(ch[nq],ch[q],sizeof ch[q]);
                    fa[nq]=fa[q],fa[q]=fa[np]=nq;
                    for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
                }
            }
        }
        void init(){
            last=cnt=1;
            mx[cnt]=0;
            for(int i=0;i<26;i++) ch[cnt][i]=0;
        }
        void dfs(int u){
            for(int x:g[u]){
                dfs(x);
                mx[u]=max(mx[u],mx[x]);
            }
        }
        void gao(){
            for(int i=2;i<=cnt;i++) g[fa[i]].pb(i);
            dfs(1);
            for(int i=2;i<=cnt;i++) ans+=max(0,len[i]-max(mx[i],len[fa[i]]));
            for(int i=1;i<=cnt;i++) g[i].clear();
        }
        void solve(){
            int m=strlen(s+1);
            int u=1,l=0;
            for(int i=1;i<=m;i++){
                int c=s[i]-'a';
                while(!ch[u][c]&&u!=1) u=fa[u],l=len[u];
                if(ch[u][c]) u=ch[u][c],l++;
                mx[u]=max(mx[u],l);
            }
        }
    }sam;
    int main(){
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            scanf("%d",&m);
            scanf("%s",s+1);
            n=strlen(s+1);
            sam.init();
            for(int i=1;i<=n;i++) sam.insert(s[i]-'a');
            ans=0;
            rep(i,1,m){
                scanf("%s",s+1);
                sam.solve();
            }
            sam.gao();
            printf("Case %d: %lld
    ",cas,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    django include
    @RequestParam 传值乱码问题
    View Merge 在安全控制上的变化,是 BUG 还是增强 ?
    postMessage实现跨域iframe自适应
    java.lang.IllegalStateException: Service id not legal hostname
    【以前的空间】 单调队列系列
    【以前的空间】 单调队列系列
    【以前的空间】 单调队列系列
    JAVA线程池shutdown和shutdownNow的区别
    JAVA线程池shutdown和shutdownNow的区别
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13922646.html
Copyright © 2020-2023  润新知