• HDU 6138 Fleet of the Eternal Throne(AC自动机)


    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6138

    【题目大意】

      给出一些串,询问第x个串和第y个串的公共子串,
      同时要求该公共子串为某个串的前缀。求最长符合要求的答案

    【题解】

      我们对所有串构建AC自动机,将两个询问串之一在AC自动机上mark所有的匹配位置
      另一个串在mark的地方寻找最长匹配即可

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring> 
    using namespace std;
    const int N=100010;
    int ans;
    namespace AC_DFA{
        const int Csize=27; 
        int tot,son[N][Csize],sum[N],fail[N],q[N],dph[N],vis[N];
        void Initialize(){
            memset(dph,0,sizeof(int)*(tot+1)); 
            memset(fail,0,sizeof(int)*(tot+1));
            memset(sum,0,sizeof(int)*(tot+1));
            for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0;
            tot=0; fail[0]=-1;
        }
        inline int Tr(char ch){return ch-'a';}
        int Insert(char *s){
            int x=0;
            for(int l=strlen(s),i=0,w;i<l;i++){
                if(!son[x][w=Tr(s[i])]){
                    son[x][w]=++tot;
                    dph[tot]=i+1;
                }x=son[x][w]; 
            }sum[x]++;
            return x;
        }
        void MakeFail(){
            int h=1,t=0,i,j,x;
            for(i=0;i<Csize;i++)if(son[0][i])q[++t]=son[0][i];
            while(h<=t)for(x=q[h++],i=0;i<Csize;i++)
            if(son[x][i]){
                fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i];
            }else son[x][i]=son[fail[x]][i];
        }
        void Cal(char *s){
            memset(vis,0,sizeof(vis));
            for(int l=strlen(s),i=0,x=0,w;i<l;i++){
                while(!son[x][Tr(s[i])])x=fail[x];
                x=son[x][Tr(s[i])];
                for(int j=x;j;j=fail[j])vis[j]=1;
            }
        }
        void Find(char *s){
            for(int l=strlen(s),i=0,x=0,w;i<l;i++){
                while(!son[x][Tr(s[i])])x=fail[x];
                x=son[x][Tr(s[i])];
                for(int j=x;j;j=fail[j])if(vis[j])ans=max(ans,dph[j]);
            }
        }
    }
    char s[110][N];
    int T,n;
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            using namespace AC_DFA;
            Initialize();
            for(int i=1;i<=n;i++){
                scanf("%s",s[i]);
                Insert(s[i]);
            }int q;
            MakeFail();
            scanf("%d",&q);
            while(q--){
                int x,y; ans=0;
                scanf("%d%d",&x,&y);
                Cal(s[x]); Find(s[y]);
                printf("%d
    ",ans);
            }
        }return 0;
    }
  • 相关阅读:
    C#验证类(使用正则表达式)
    SQL数据库还原语句
    JS键盘或鼠标事件
    列表针对列宽度自动调整显示内容,超长以...缩写结尾
    SQL按照日、周、月、年统计数据 (转自BLEACH的blog)
    SQL利用Case When Then多条件判断
    调用Web服务:请求因HTTP状态401失败:Unauthorized
    IFrame自动适应宽高,去掉空白
    Asp调用WebService事例
    Timer不执行Elapsed事件的解决办法
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu6138.html
Copyright © 2020-2023  润新知