• Spoj 7758. Growing Strings AC + dp


    题目意思   就是说一个给你 N 个单词,然后着 N 个单词中一个单词肯能包含另外一个单词,这个单词可能有包含另外一个单词,这样一直下去,做多能包含多少个单词;

    思路        想想这题不用 AC 自动机会怎么做;首先对单词排序,然后用DP 的思想,后面一个单词如果包含前面那个单词,则从那个单词的最优值 +1 ,但N 太大了 不行;

                 转成  自动机的思想就是   先把所有字符  插入到字典数;你会发现,从根节点往后面走,知道找到一条路结束了,那么中间经过的那  N 个单词的后缀,都是符合字串包含字串的;还有一个问题就是;虽然字串包含字串,但结果不一定就是最优的;可能在这条路径的中间位置会出现他包含了一连续的字串,很明显,他所包含的那些字串不是这条路径上的;是另外一条路径上的,而结果  明显要更优;所以,这里应该取最优值不是;考虑这条路径上的每一个节点,要么他是从自己本身的这条路径上继承过来的最优值,或者是起点不是 根节点的, 但他匹配的最长公共前缀却能获的最优值;

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    using namespace std;
     
    struct date
    {
        date *next[26],*fail;
        int sum,cnt;
    }tree[1123456],*que[1123456],*root;
     
    int res[11000],tail,head,ptr,N;
     
    date *creat_node( )
    {
        for( int i = 0; i < 26; i++ )
           tree[ptr].next[i] = NULL;
        tree[ptr].fail = NULL;
        tree[ptr].sum = 0;
        tree[ptr].cnt = 0;
        return &tree[ptr++];
    }
     
    void inint( )
    {
        tail = head = ptr = 0;
        root = creat_node( );
        root->fail = root;
    }
     
    void insert( char *word,int i )
    {
        date *temp = root;
        while( *word )
        {
            int num = *word - 'a';
            if( temp->next[num] == NULL )
                temp->next[num] = creat_node();
                temp = temp->next[num];
            word++;
        }
        temp->cnt = i;
    }
     
    int build_AC( )
    {
        que[tail++] = root;
        while( tail > head )
        {
            date *temp = que[head++];
            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];
                     temp->next[i]->sum = max( temp->next[i]->fail->sum,temp->sum );
                if(  temp->next[i]->cnt )
                {
                     temp->next[i]->sum++;
                     res[temp->next[i]->cnt] = temp->next[i]->sum;
                }
                que[tail++] = temp->next[i];
            }
            else
            {
                if( temp == root ) temp->next[i] = root;
                else               temp->next[i] = temp->fail->next[i];
            }
        }
        int ans = 0;
        for( int i = 1; i <= N; i++ )
        ans = max( ans,res[i] );return ans;
    }
    int main( )
    {
        char str[1100];
        while( scanf("%d",&N) &&N )
        {
            inint( );
            for( int i = 1; i <= N; i++ )
            {
                scanf("%s",&str);
                insert( str,i );
            }
            printf( "%d\n",build_AC( ) );
        }
        return 0;
    }
     
    

      

  • 相关阅读:
    杭电1029--Ignatius and the Princess IV(哈希)
    杭电1465--不容易系列之一
    杭电1021--Fibonacci Again
    杭电5018--Revenge of Fibonacci
    UVa10651(记忆化搜索)
    <Win32_5>深入浅出Win32的计时器
    偷个空,写个博客——各种沟通各种纠结
    Arbitrage HDU
    常用的字符串处理方法
    无法捕获的异常:MissingMethodException
  • 原文地址:https://www.cnblogs.com/wulangzhou/p/3016655.html
Copyright © 2020-2023  润新知