• 【XSY2989】字符串


    题目来源:NOI2018模拟测试赛(二十六)

    题解:

    首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果;

    一个串出现有三种情况:在前半部分,在后半部分或穿过中间;

    对于前两种情况,由于n很小,可以直接在AC自动机跑状压DP,对于第三种情况特殊处理一下,就是对于所有子串的所有前缀,判断以这个前缀为结尾能否构造出这个串,有则累加答案就好了,具体见代码。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #define inf 2147483647
     8 #define eps 1e-9
     9 #define mod 998244353
    10 using namespace std;
    11 typedef long long ll;
    12 typedef double db;
    13 struct ac{
    14     int fa,fail,son[2],s,t;
    15 }t[200001];
    16 int n,m,nw,tmp,ans=0,len,cnt=0,num[2001],f[2][2001][64];
    17 char s[101];
    18 void ins(char *s,int len,int id){
    19     int nw=0;
    20     for(int i=1;i<=len;i++){
    21         if(!t[nw].son[s[i]-'0']){
    22             t[nw].son[s[i]-'0']=++cnt;
    23             num[cnt]=s[i]-'0';
    24             t[cnt].fa=nw;
    25         }
    26         nw=t[nw].son[s[i]-'0'];
    27     }
    28     t[nw].s|=(1<<id-1);
    29 }
    30 void AC(){
    31     queue<int>q;
    32     for(int i=0;i<=1;i++){
    33         if(t[0].son[i]){
    34             q.push(t[0].son[i]);
    35             t[t[0].son[i]].fail=0;
    36         }
    37     }
    38     while(!q.empty()){
    39         int u=q.front();
    40         q.pop();
    41         t[u].s|=t[t[u].fail].s;
    42         for(int i=0;i<=1;i++){
    43             if(t[u].son[i]){
    44                 t[t[u].son[i]].fail=t[t[u].fail].son[i];
    45                 q.push(t[u].son[i]);
    46             }else t[u].son[i]=t[t[u].fail].son[i];
    47         }
    48     }
    49 }
    50 int getfa(int u){
    51     int ret=0;
    52     for(int nw=u;nw;nw=t[nw].fa){
    53         u=t[u].son[num[nw]^1];
    54         ret|=t[u].s;
    55     }
    56     return ret;
    57 }
    58 int main(){
    59     scanf("%d%d",&n,&m);
    60     for(int i=1;i<=n;i++){
    61         scanf("%s",s+1);
    62         len=strlen(s+1);
    63         ins(s,len,i);
    64         reverse(s+1,s+len+1);
    65         for(int j=1;j<=len;j++){
    66             s[j]=((s[j]-'0')^1)+'0';
    67         }
    68         ins(s,len,i);
    69     }
    70     AC();
    71     f[0][0][0]=1;
    72     for(int tt=1;tt<=m;tt++){
    73         nw^=1;
    74         memset(f[nw],0,sizeof(f[nw]));
    75         for(int i=0;i<=cnt;i++){
    76             for(int j=0;j<(1<<n);j++){
    77                 for(int k=0;k<=1;k++){
    78                     f[nw][t[i].son[k]][j|t[t[i].son[k]].s]=(f[nw][t[i].son[k]][j|t[t[i].son[k]].s]+f[nw^1][i][j])%mod;
    79                 }
    80             }
    81         }
    82     }
    83     for(int i=0;i<=cnt;i++){
    84         tmp=getfa(i);
    85         for(int j=0;j<(1<<n);j++){
    86             if((tmp|j)==(1<<n)-1){
    87                 ans=(ans+f[nw][i][j])%mod;
    88             }
    89         }
    90     }
    91     printf("%d",ans);
    92     return 0;
    93 }
  • 相关阅读:
    Android 编译命令 make j8 2>&1 | tee build.log 解释
    Linux时间函数之gettimeofday()函数之使用方法
    转:RSA算法原理说明
    转: 各个密码算法的实现(未验证)
    转:修改Android签名证书keystore的密码、别名alias以及别名密码
    转:Eclipse ADT的Custom debug keystore所需证书规格
    转:如何转换Android打包用jks格式keystore证书为Air用pkcs12格式p12证书
    转: 关于流量控制与令牌桶介绍
    转:sublime2 官方网址
    转:Mac OS X下Sublime Text (V2.0.1)破解
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10062939.html
Copyright © 2020-2023  润新知