zoukankan      html  css  js  c++  java
  • fzu 2128 AC自动机

    链接   http://acm.fzu.edu.cn/problem.php?pid=2128

    解题方法  首先考虑暴力,,就是拿每一个字符串在匹配串里面找到所有位置,然后从头到尾不断更新最长的合理位置pos 同时记录出 最长的长度; 想到这样会超时,所以 AC 自动机一下,找到任意一个后缀最长能匹配的位置 方法是: 在构建自动机的 fail 指针的时候,找到任意位置的任意字符最长公共前缀的时候看那个位置是否有单词存在;

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct date{
       date *next[26],*fail;
       int len; bool flag;
    }tree[100005],*que[100005],*root;
    int N,total,tail,hed; char str[1000006],cha[102];
    date *creat( )
    {
        for( int i = 0; i < 26; i++ )
        tree[total].next[i] = NULL;
        tree[total].fail = NULL;
        tree[total].flag = false;
        tree[total].len = 1000000;
        return &tree[total++];
    }
    void inint( )
    {
        total = hed = tail = 0;
        root = creat();
        root->fail = root;
    }
    void insert( char *word,int len )
    {
        date *temp = root;
        while( *word )
        {
            int num = *word - 'a';
            if( temp->next[num] == NULL )
                temp->next[num] = creat();
            temp = temp->next[num];
            word++;
        }
        temp->len = len-1;
        temp->flag = true;
    }
    void build( )
    {
        que[tail++] = root;
        while( tail > hed )
        {
            date *temp = que[hed++];
            for( int i = 0; i < 26; i++ )
            if( temp->next[i] != NULL ){
                if( temp == root )temp->next[i]->fail = root;
                else  temp->next[i]->fail = temp->fail->next[i];
                if( temp->fail->next[i]->flag )
                    temp->next[i]->len = min( temp->next[i]->len,temp->fail->next[i]->len );
                que[tail++] = temp->next[i];
            }
            else {
              if( temp == root )temp->next[i] = root;
              else temp->next[i] = temp->fail->next[i];
            }
        }
    }
    short int res[1000006];
    inline int max( int a,int b){return a>b?a:b;}
    inline int min( int a,int b){return a>b?b:a;}
    void search( char *word )
    {
        int t = 0; date *temp = root; int len = strlen(word);
        while( *word )
        {
            int num = *word - 'a';
            temp = temp->next[num];
            res[t] = temp->len;
            word++; t++;
        }
        int pre = 0; int Max = 0;
        for( int i = 0; i < len; i++ ){
            pre = min( pre + 1,res[i] );
            Max = max( Max,pre );
        }
        printf("%d
    ",Max);
    }
    int main( )
    {
        while( scanf("%s",&str) != EOF )
        {
            scanf("%d",&N); inint( );
            for( int i = 1; i <= N; i++ ){
                scanf("%s",&cha); insert(cha,strlen(cha));
            }
            build( );   search( str );
        }
        return 0;
    }
    

      

  • 相关阅读:
    Windows8.1 + Nvidia cuda8.0 + Vs2015
    读《鲜花帝国》有感
    oracle-sql书写
    oracle--聚合函数和case when结合使用
    oracle正则表达式
    oracle中case when使用
    oracle分区表之列表分区
    linux下oracl字符集修改(WE8ISO8859P1 --> ZHS16GBK)
    linux 下安装oracle数据库
    oracle学习笔记
  • 原文地址:https://www.cnblogs.com/wulangzhou/p/3330804.html
Copyright © 2011-2022 走看看