zoukankan      html  css  js  c++  java
  • Rikka with String HDU 6086

    题解: 要是这个东西没有反对称的概念,我们直接AC自动机+dp就可以很愉快的解决了,但是现在有了这个反对称的原则,在不考虑跨过中间的部分的话这个还是很容易的解决的,dp[i][j][k][state]代表到了第i个位置,在左串的j节点,右边的k节点此时的state,但是这样子的话我们发现了一个问题就是这个复杂度没有很好的利用反对称的这个性质。

    假如我们现在有一个00101的串,我们在左边匹配了01011也相当于匹配了这个串,所以这个复杂度就减少了。

    然后就是考虑跨过了中间位置的字符串,然后暴力枚举就行了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXNODE = 2500;
    const int SIGMA_SIZE = 2;
    const LL MOD = 998244353;
    
    struct ACauto {
        int next[MAXNODE][SIGMA_SIZE], fail[MAXNODE], end1[MAXNODE], end2[MAXNODE];
        int root,sz;
    
        int newnode() {
            for (int i = 0; i < SIGMA_SIZE; i++)
                next[sz][i] = -1;
            end1[sz] = 0;
            end2[sz++] = 0;
            return sz - 1;
        }
    
        void init() {
            sz = 0;
            root = newnode();
        }
    
        void insert1(char *buf, int id) {
            int len = strlen(buf);
            int now = root;
            for (int i = 0; i < len; i++) {
                if (next[now][buf[i] - '0'] == -1)
                    next[now][buf[i] - '0'] = newnode();
                now = next[now][buf[i] - '0'];
            }
            end1[now] |= (1 << id);
        }
    
        void insert2(char *buf, int id) {
            int len = strlen(buf);
            int now = root;
            for (int i = 0; i < len; i++) {
                if (next[now][buf[i] - '0'] == -1)
                    next[now][buf[i] - '0'] = newnode();
                now = next[now][buf[i] - '0'];
            }
            end2[now] |= (1 << id);
        }
    
        void build() {
            queue <int> Q;
            fail[root] = root;
            for (int i = 0; i < SIGMA_SIZE; i++) {
                if (next[root][i] == -1)
                    next[root][i] = root;
                else {
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while (!Q.empty()) {
                int now = Q.front();
                Q.pop();
                end1[now] |= end1[fail[now]];
                end2[now] |= end2[fail[now]];
                for (int i = 0; i < SIGMA_SIZE; i++) {
                    if (next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else {
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
            }
        }
    
    } ac;
    
    int n, L;
    char s[30], t[30], str[60];
    LL dp[13][2700][(1 << 6) + 10];
    
    int main() {
        //freopen("in.txt", "r", stdin);
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%d%d", &n, &L);
            ac.init();
            for (int i = 0; i < n; i++) {
                scanf("%s", s);
                ac.insert1(s, i);
                //cout << i << endl;
               // cout << s << endl;
                int len = strlen(s);
                for (int j = 0; j < len; j++)
                    t[j] = s[len - 1 - j] == '0' ? '1' : '0';
                t[len] = '';
               ac.insert1(t, i);
                //printf("****
    ");
               // cout << t << endl;
                for (int j = 0; j < len - 1; j++) {
                    string s1 = "", s2 = "";
                    for (int k = j; k >= 0; k--) s1 += s[k];
                    for (int k = j + 1; k < len; k++) s2 += s[k];
                    //cout << " : " << s1 << "  " << s2 << endl;
                    bool flag = true;
                    for (int k = 0; k < (int)s1.length() && k < (int)s2.length(); k++) {
                        if (s1[k] == s2[k]) {
                            flag = false;
                            break;
                        }
                    }
                    if (!flag) continue;
                    reverse(s1.begin(), s1.end());
                    //cout << " -- " << s1 << endl;
                    for (int k = (j + 1) * 2; k < len; k++) {
                        s1 = (s[k] == '0' ? '1' : '0') + s1;
                    }
                    //cout << s1 << endl;
                    strcpy(str, s1.c_str());
                  //  printf("****
    ");
                    //printf("%s
    ",str);
                    ac.insert2(str, i);
                }
            }
            ac.build();
            memset(dp, 0, sizeof(dp));
            dp[0][0][0] = 1;
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < ac.sz; j++) {
                    for (int S = 0; S < (1 << n); S++) {
                        if (dp[i%2][j][S] == 0) continue;
                        for (int k = 0; k < SIGMA_SIZE; k++) {
                            int ni = i + 1, nj = ac.next[j][k], nS = S | ac.end1[nj];
                            if (i == L - 1) nS |= ac.end2[nj];
                            dp[ni%2][nj][nS] = (dp[ni%2][nj][nS] + dp[i%2][j][S]) % MOD;
                        }
                        dp[i%2 ][j][S] = 0;
                    }
                }
            }
            LL ans = 0;
            for (int i = 0; i < ac.sz; i++) {
                ans = (ans + dp[L%2][i][(1 << n) - 1]) % MOD;
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    Java安全之JNDI注入
    Visual Studio 2019 升级16.8之后(升级.Net 5),RazorTagHelper任务意外失败
    .Net Core 3.1升级 .Net 5后出现代码错误 rzc generate exited with code 1.
    重走py 之路 ——普通操作与函数(三)
    重走py 之路 ——字典和集合(二)
    设计模式结(完结篇)
    重走py 之路 ——列表(一)
    RestfulApi 学习笔记——分页和排序(五)
    RestfulApi 学习笔记——查询与过滤还有搜索(五)
    Android开发 Error:The number of method references in a .dex file cannot exceed 64K.Android开发 Error:The number of method references in a .dex file cannot exceed 64K
  • 原文地址:https://www.cnblogs.com/Heilce/p/7402664.html
Copyright © 2011-2022 走看看