zoukankan      html  css  js  c++  java
  • 2018 北京区域赛H

    ac自动机+dp

    把串的每位翻转一下插入$ac$自动机

    $dp[i][j][k]$表示走了$j$步到自动机上$i$节点是否包含了串 转移即可

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2005;
    namespace ac 
    {
        struct data {
            int danger, fail; 
            int c[2];
        } t[maxn];
        int root, size;
        int q[maxn * 10];
        void ins(char *s)
        {
            int now = root, l = strlen(s + 1);
         //   printf("s = %s
    ", s + 1);
            for(int i = 1; i <= l; ++i)
            {
                if(!t[now].c[s[i] - '0']) t[now].c[s[i] - '0'] = ++size;
                now = t[now].c[s[i] - '0'];
            }
    //        printf("now=%d
    ", now);
            t[now].danger = 1; 
        } 
        void get_fail()
        {
            int l = 1, r = 0;
            for(int i = 0; i < 2; ++i) if(t[0].c[i]) q[++r] = t[0].c[i];
            while(l <= r) {
                int u = q[l++];
                t[u].danger |= t[t[u].fail].danger;
                for(int i = 0; i < 2; ++i) {
                    int &v = t[u].c[i];
                    if(!v) v = t[t[u].fail].c[i];
                    else t[v].fail = t[t[u].fail].c[i], q[++r]=v;
                }
            }
        }
    } using namespace ac;
    int n, m;
    long long dp[maxn][45][2];
    char s[maxn];
    int main() {
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%d%d%s", &n, &m, s + 1);
            size = 0;
            ins(s);
            for(int i = 1; i <= n; ++i) {
                if(s[i] == '0') {
                    s[i] = '1';
                    ins(s);
                    s[i] = '0';
                } else {
                    s[i] = '0';
                    ins(s);
                    s[i] = '1';
                }
            }
            get_fail();
            memset(dp, 0, sizeof(dp));
            dp[root][0][0] = 1;
            for(int i = 0; i < m; ++i) {
                for(int j = 0; j <= size; ++j) {
    
                    int x = t[j].c[0], y = t[j].c[1];
                    
            //        printf("j = %d x = %d y = %d
    ", j, x, y);
                    if(!t[x].danger) dp[x][i + 1][0] += dp[j][i][0];
                    else dp[x][i + 1][1] += dp[j][i][0];
                    if(!t[y].danger) dp[y][i + 1][0] += dp[j][i][0];
                    else dp[y][i + 1][1] += dp[j][i][0];
                    dp[x][i + 1][1] += dp[j][i][1];
                    dp[y][i + 1][1] += dp[j][i][1];
                }
            }
        //    printf("size = %d
    ", size);
        //    for(int i = 0; i <= size; ++i)
        //        for(int j = 1; j <= m; ++j)
        //            printf("dp[%d][%d][0] = %lld dp[%d][%d][1] = %d
    ", i, j, dp[i][j][0], i, j, dp[i][j][1]);
            long long ans = 0;
            for(int i = 0; i <= size; ++i)
                ans += dp[i][m][1];
            printf("%lld
    ", ans);
            for(int i = 0; i <= size; ++i) {
                t[i].danger = t[i].fail = 0;
                t[i].c[0] = t[i].c[1] = 0;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    刷新页面的问题
    JS属性
    1-4_基本概念_进程间通信及同步
    1-3_基本概念_程序&进程
    1-2_基本概念_用户和组&目录、链接及文件
    1-1_基本概念_内核&shell
    d 操作系统概述
    对比生成测试算法用例
    简单的排序算法:冒泡排序法
    简单的排序算法:插入排序法
  • 原文地址:https://www.cnblogs.com/19992147orz/p/11712344.html
Copyright © 2011-2022 走看看