空罐Cans (ac自动机 dp)

原创 2013年12月03日 12:26:57

忘记了 这一句  val[u] |= val[f[u]];///!!!

参考:http://blog.csdn.net/no__stop/article/details/8943271

另有:

hdu 3341 Lost's revenge关于压缩的技巧

lightoj 1427 Substring Frequency (II) (ac自动机)在fail树上的拓扑

。。。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FD(i, b, a) for(int i = (b); i >= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(a, v) memset(a, v, sizeof(a))
#define PB push_back
#define MP make_pair
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MOD = 10007;

const int maxn = 1555;
const int SIG = 4;

int dp[2][111][maxn];
int ans1, ans2;

int n, p;

struct AC{
    int ch[maxn][SIG];
    int f[maxn];
    int dep[maxn];
    int val[maxn];
    int sz;
    int newnode(int deep)///!!!
    {
        CLR(ch[sz], 0);
        dep[sz] = deep;
        val[sz] = 0;
        return sz++;
    }
    void init()
    {
        sz = 0;
        newnode(0);
    }
    int idx(char c) { return c-'a'; }
    void insert(char *s)
    {
        int u=0,n=strlen(s);
        int d = 0;
        for(int i=0;i<n;i++)
        {
            d++;
            int c=idx(s[i]);
            if(!ch[u][c]) ch[u][c] = newnode(d);
            u = ch[u][c];
        }
        val[u] = 1;
    }
    void getFail()
    {
        queue<int> q;
        f[0] = 0;
        for(int c = 0; c < SIG; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); }
        }

        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIG; 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];
                val[u] |= val[f[u]];///!!!
            }
        }
    }
    void solve(char *s)
    {
        int len = strlen(s);
        CLR(dp, 0);
        int fla = 0;
        int uu = 0;
        for (int i = 0; i < len; i++)
        {
            int c = idx(s[i]);
            uu = ch[uu][c];
            if (val[uu]) fla = 1;
        }
        if (fla) { ans1 = 0; ans2 = 1; return; }
        dp[0][len][uu] = 1;

        int now, next;
        now = 0;

        for (int i = 0; i <= p; i++)
        {
            next = now ^ 1;
            for (int r = 0; r < sz; r++)
            {
                ans1 += dp[now][0][r];
                ans1 %= MOD;///!!!
                for (int j = 1; j <= 100; j++)
                {
                    int tmp = dp[now][j][r];
                    if (!tmp) continue;
                    if (val[r]) { ans2 += tmp; ans2 %= MOD; continue; }///!!!
                    for (int g = 0; g < 4; g++)
                    {
                        int u = ch[r][g];
                        dp[next][j + 1][u] += tmp;
                        dp[next][j + 1][u] %= MOD;
                    }
                    if (dep[r] <= j - 1) dp[next][j - 1][r] += tmp, dp[next][j - 1][r] %= MOD;
                    else dp[next][j - 1][f[r]] += tmp, dp[next][j - 1][f[r]] %= MOD;
                }
            }
            CLR(dp[now], 0);
            now ^= 1;
        }
    }

}ac;

char s[maxn];
char ca[maxn];
int main()
{
    while (~scanf("%s", s))
   {
        scanf("%d%d", &p, &n);
        ac.init();
        for (int i = 1; i <= n; i++)
        {
            scanf("%s", ca);
            ac.insert(ca);
        }
        ac.getFail();
        ans1 = ans2 = 0;
        ac.solve(s);
        printf("%d %d\n", ans1, ans2);
   }
    return 0;
}


AC自动机+DP小结 (一)

好久没有更新博客了,最近真是懒到家了,南京赛前重点复习了下AC自动机+DP方面的题,写下来总结一下。 HDU 2457  DNA repair http://acm.hdu.edu.cn/showpr...
  • dyx404514
  • dyx404514
  • 2013年11月13日 11:12
  • 3397

ac自动机最详细的讲解,让你一次学会ac自动机。

在没学ac自动机之前,觉得ac自动机是个很神奇,很高深,很难的算法,学完之后发现,ac自动机确实很神奇,很高深,但是却并不难。 我说ac自动机很神奇,在于这个算法中失配指针的妙处(好比kmp算法中的...
  • creatorx
  • creatorx
  • 2017年05月02日 19:51
  • 14544

POJ 1625 ac自动机+高精度dp

Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 7469   Acce...
  • u012358934
  • u012358934
  • 2014年02月05日 12:52
  • 1183

空罐 AC自动机 + DP 好题

链接:http://zerojudge.tw/ShowProblem?problemid=b179 做这道题首先要对ac自动机理解透彻!! 蛮好的一道题目,每一天字符串除了会在尾部扩展一个,开头的...
  • haha593572013
  • haha593572013
  • 2012年10月15日 20:31
  • 961

郑厂长系列故事——新闻净化 AC自动机 DP

#include #include #include #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ?...
  • cqlf__
  • cqlf__
  • 2013年04月28日 20:55
  • 1558

【BZOJ1030】【Tyvj1806】文本生成器,AC自动机+DP

生活不分学期,没有暑假能够休息。
  • xym_CSDN
  • xym_CSDN
  • 2016年04月04日 21:12
  • 268

Uva11468 AC自动机+概率dp

这题把AC自动机和dp结合了下,题意就是给你一些模式串,给你选择每个字符的概率,让你选择L个字符,求不出现模式串的概率。 先把模式串都插入AC自动机,用一个match数组记录该节点是否是单词节点,特...
  • qq415200973
  • qq415200973
  • 2013年08月31日 15:08
  • 516

BZOJ1030 [JSOI2007]文本生成器【AC自动机+DP】

题意:给定n个字符串,要求构造长度为m的字符串使其包含至少一个给定字符串,求方案数。 AC自动机+DP肯定是显然的啦。但是要求“至少一个”被包含肯定不好搞,所以我们反过来想,用总方案数-一个也不包含...
  • u011431896
  • u011431896
  • 2015年04月24日 08:54
  • 370

poj 1625 Censored! 【AC自动机 + DP + 强力大数模版】

1y,还是这个大数模版给力,自己敲了个动态的大数模版结果连加法都算不对。。。 #include #include #include #include #include #include usin...
  • zz_1215
  • zz_1215
  • 2012年05月16日 10:59
  • 549

bzoj1559 [JSOI2009]密码(AC自动机+状压DP)

bzoj1559 [JSOI2009]密码原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=155题意: 给出n个子串,问有多少长度为L的字符...
  • Bfk_zr
  • Bfk_zr
  • 2017年12月17日 11:47
  • 49
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:空罐Cans (ac自动机 dp)
举报原因:
原因补充:

(最多只允许输入30个字)