• HDU 6086 Rikka with String


    Rikka with String

    http://acm.hdu.edu.cn/showproblem.php?pid=6086

    题意:

      求一个长度为2L的,包含所给定的n的串,并且满足非对称。

    分析:

      AC自动机+状压dp。

      首先给这个n个串,建立AC自动机。然后去枚举长度为L的一个串,就可以知道另一半了。

      如果给定的串完全存在于左边或者右边,那么直接往AC自动机加入这个串或者取反后的反串。如果是跨越中间,那么暴力的把所有的串,从中间切开,然后判断是否合法,加入到AC自动机上就行,如果长度枚举到了i-1的时候,这些串的状态才有用。

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<cmath>
      6 #include<cctype>
      7 #include<set>
      8 #include<queue>
      9 #include<vector>
     10 #include<map>
     11 using namespace std;
     12 typedef long long LL;
     13 
     14 inline int read() {
     15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     17 }
     18 
     19 const int mod = 998244353;
     20 int ch[2500][2], sta1[2500], sta2[2500], fail[2500], q[2500], dp[2][2500][70];
     21 int Index;
     22 char s[100], t[100], a[100], b[100];
     23 
     24 void Insert(char *s,int n,int id,bool f) {
     25     int u = 0;
     26     for (int i = 0; i < n; ++i) {
     27         int c = s[i] - '0';
     28         if (!ch[u][c]) ch[u][c] = ++Index;
     29         u = ch[u][c];
     30     }
     31     if (f) sta1[u] |= (1 << id);
     32     else sta2[u] |= (1 << id);
     33 }
     34 void build() {
     35     int L = 1, R = 0;
     36     for (int i = 0; i < 2; ++i) if (ch[0][i]) q[++R] = ch[0][i];
     37     while (L <= R) {
     38         int u = q[L ++];
     39         for (int c = 0; c < 2; ++c) {
     40             int v = ch[u][c];
     41             if (!v) { ch[u][c] = ch[fail[u]][c]; continue; }
     42             int p = fail[u]; while (p && !ch[p][c]) p = fail[p];
     43             q[++R] = v;
     44             fail[v] = ch[p][c];
     45             sta1[v] |= sta1[fail[v]], sta2[v] |= sta2[fail[v]];
     46         }
     47     }
     48 }
     49 void update(char *s,int n,int id) {
     50     int c1 = 0, c2 = 0, f = 0;
     51     for (int i = 0; i < n - 1; ++i) {
     52         c1 = c2 = f = 0;
     53         for (int j = i; j >= 0; --j) a[c1 ++] = s[j];a[c1] = '';
     54         for (int j = i + 1; j < n; ++j) b[c2 ++] = s[j]; b[c2] = '';
     55         for (int j = 0; j < c1 && j < c2; ++j) if (a[j] == b[j]) { f = 1; break; }
     56         if (f) continue;
     57         for (int j = c1; j < c2; ++j) a[j] = b[j] == '0' ? '1' : '0';
     58         reverse(a, a + max(c1, c2));
     59         Insert(a, max(c1, c2), id, 0); // 长度为max(c1,c2)!!! 
     60     }
     61 }
     62 void init() {
     63     memset(dp, 0, sizeof(dp));
     64     memset(ch, 0, sizeof(ch));
     65     memset(fail, 0, sizeof(fail));
     66     memset(sta1, 0, sizeof(sta1));
     67     memset(sta2, 0, sizeof(sta2));
     68 }
     69 inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
     70 void solve() {
     71     init();
     72     int n = read(), L = read(), len;
     73     for (int i = 0; i < n; ++i) {
     74         scanf("%s", s); len = strlen(s);
     75         Insert(s, len, i, 1);
     76         for (int j = 0; j < len; ++j) t[j] = s[j]; 
     77         reverse(t, t + len);
     78         for (int j = 0; j < len; ++j) t[j] = t[j] == '0' ? '1' : '0';
     79         Insert(t, len, i, 1);
     80         update(s, len, i);
     81     }
     82     build();
     83     dp[0][0][0] = 1;
     84     int All = (1 << n) - 1, now = 0;
     85     for (int i = 0; i < L; ++i, now ^= 1) 
     86         for (int j = 0; j <= Index; ++j) 
     87             for (int s = 0; s <= All; ++s) {
     88                 if (dp[now][j][s] <= 0) continue;
     89                 for (int c = 0; c < 2; ++c) {
     90                     int nv = ch[j][c], ns = s | sta1[nv];
     91                     if (i == L - 1) ns |= sta2[nv];
     92                     add(dp[now ^ 1][nv][ns], dp[now][j][s]);
     93                 }
     94                 dp[now][j][s] = 0;
     95             }
     96     int ans = 0;
     97     for (int i = 0; i <= Index; ++i) add(ans, dp[now][i][All]);
     98     printf("%d
    ",ans % mod);
     99 }
    100 int main() { 
    101     for (int T = read(); T --; ) solve();
    102     return 0;
    103 }
  • 相关阅读:
    CentOS 5.5和5.6 安装后的网络配置
    CentOS 5.5 系统安全配置
    printk: messages suppressed
    “找不到出路的”vb6.0
    用户控件的烦扰
    rman恢复
    oracle数据字典
    oracle自关联表的子删父变功能实现
    oracle自治事务
    oracle表空间更名
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10091024.html
Copyright © 2020-2023  润新知