zoukankan      html  css  js  c++  java
  • fzu 2246(ac 自动机)

    fzu 2246(ac 自动机)

    题意:

    某一天YellowStar学习了AC自动机,可以解决多模式匹配问题。YellowStart当然不会满足于此,它想进行更深入的研究。

    YellowStart有一个母串(S),以及(m)个询问串(T),它发现如果把母串删除掉一个子串,把剩余的串按原先顺序拼接起来,某些询问串(T)就可能出现在这个新的母串中。

    现在,对于第(i)个询问串(T_i),YellowStar想知道,母串最多可以删除多长的子串,使得该询问串出现在新的母串的子串中。

    (|S| <= 1e5)
    $sum{|T_i|} <= 1e5 $

    思路:利用ac自动机处理出每个查询串的每个前缀在S中最先出现的位置 和 每个后缀在S中最后出现的位置,取
    (max(sufpos[i+1] - prepos[i] - 1))即可

    具体的做法 是将所有询问串 正着一遍插入ac自动机,对于串S 类似于找子串的方式更新当前位置匹配的所有前缀,然后再反着插入做一遍即可

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #define LL long long
    using namespace std;
    
    const int N = 1e5 + 10;
    char S[N],P[N],tmp[N],S_r[N];
    int m, tot;
    int len[N],st[N];
    int pre_id[N],suf_id[N];
    int pre_pos[N],suf_pos[N];
    const int SIZE = 26;
    const int MAXNODE = 1e5 + 10;
    
    struct AC{
        int ch[MAXNODE][SIZE];
        int f[MAXNODE],last[MAXNODE],val[MAXNODE];
        int sz;
        void init(){sz = 1;memset(ch[0],0,sizeof(ch[0]));}
        int idx(char c){return c - 'a';}
        int _insert(char *s, int st,int len,int *p){
            int u = 0;
            for(int i = 0;i < len;i++){
                int c = idx(s[i + st]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof ch[sz]);
                    val[sz] = 0;
                    ch[u][c] = sz++;
                }
                u = ch[u][c];
                val[u] = 1;
                p[i + st] = u;
            }
            return u;
        }
        void getFail(){
            queue<int> q;
            f[0] = 0;
            for(int c = 0;c < SIZE;c++){
                int u = ch[0][c];
                if(u){
                    f[u] = 0;
                    q.push(u);
                    last[u] = 0;
                }
            }
            while(!q.empty()){
                int r = q.front();q.pop();
                for(int c = 0;c < SIZE;c++){
                    int u = ch[r][c];
                    if(!u){ch[r][c] = ch[f[r]][c];continue;}
                    q.push(u);
                    int v = f[r];
                    while(v && !ch[v][c]) v = f[v];
                    f[u] = ch[v][c];
                    last[u] = val[f[u]]?f[u]:last[f[u]];
                }
            }
        }
        void up(int u,int x,int *p){
            if(!u) return ;
            if(p[u] == -2) p[u] = x;
            up(last[u],x,p);
        }
        void Find(char *s,int *p){
            int len = strlen(s), u = 0;
            pre_pos[u] = -1;
            for(int i = 0;i < len;i++){
                int c = idx(s[i]);
                u = ch[u][c];
                up(u,i,p);
            }
        }
    }ac;
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%s",P);
            scanf("%d",&m);
            tot = 0;
            for(int i = 0;i < m;i++){
                scanf("%s",tmp);
                len[i] = strlen(tmp);
                st[i] = tot;
                for(int j = 0;j < len[i];j++) S[j + tot] = tmp[j];
                reverse(tmp,tmp + len[i]);
                for(int j = 0;j < len[i];j++) S_r[j + tot] = tmp[j];
                tot += len[i];
            }
            for(int i = 0;i < tot;i++) pre_pos[i] = suf_pos[i] = -2;
            ac.init();
            for(int i = 0;i < m;i++) ac._insert(S,st[i],len[i],pre_id);
            ac.getFail();
            ac.Find(P,pre_pos);
            ac.init();
            for(int i = 0;i < m;i++) ac._insert(S_r,st[i],len[i],suf_id);
            ac.getFail();
            int tlen = strlen(P);
            reverse(P,P + tlen);
            ac.Find(P,suf_pos);
            for(int i = 0;i < m;i++){
                int ans = -1;
                int stt = st[i],ll = len[i];
                if(pre_pos[pre_id[stt + ll - 1]] != -2) ans = max(ans, tlen - pre_pos[pre_id[stt + ll - 1]] - 1);
                if(suf_pos[suf_id[stt + ll - 1]] != -2) ans = max(ans, tlen - suf_pos[suf_id[stt + ll - 1]] - 1);
                for(int j = 0;j + 1 < ll;j++){
                    int a = pre_pos[pre_id[j + stt]];
                    int b = suf_pos[suf_id[ll - j - 2 + stt]];
                    if(a != -2 && b != -2 && tlen - b -1 - a - 1 >= 1) ans = max(ans,tlen - b - 1 - a - 1);
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    Maven关于web.xml中Servlet和Servlet映射的问题
    intellij idea的Maven项目运行报程序包找不到的错误
    修改Maven项目默认JDK版本
    刷题15. 3Sum
    刷题11. Container With Most Water
    刷题10. Regular Expression Matching
    刷题5. Longest Palindromic Substring
    刷题4. Median of Two Sorted Arrays
    刷题3. Longest Substring Without Repeating Characters
    刷题2. Add Two Numbers
  • 原文地址:https://www.cnblogs.com/jiachinzhao/p/7725289.html
Copyright © 2011-2022 走看看