字符串 - AC自动机 - 状压dp

本文探讨了在给定多个01串的情况下,如何高效找出所有长度为2n的反回文01串,这些串包含了给定的所有子串。通过使用AC自动机和巧妙的数据结构,文章详细介绍了算法的设计、实现及优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:
给定m个01串,问有多少长度为2n的反回文01串,包含这m个串。
一个01串被称为反回文的,当且仅当∀i∈[1,n],s[i]̸=s[n−i+1]\forall i\in[1,n],s[i]\not=s[n-i+1]i[1,n],s[i]̸=s[ni+1]
m≤6,n≤500,∣si∣≤100m\le6,n\le500,|s_i|\le100m6,n500,si100
题解:
首先朴素做法是建两个AC自动机。
然后你发现你可以把原串和原串reverse后每位取反的串都插到同一个AC自动机里面。对于每个节点暴力跑出其对应哪些串即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int LEN=110,TR=1210,MXS=(1<<6)+10,N=510;
char str[LEN];queue<int> q;int node_cnt,fa[TR],s[TR];
int a[LEN],fr[TR],ch[TR][2],frv[TR],dp[N][MXS][TR];
inline int ins(int *a,int n,int v)
{
    int x=1;
    for(int i=1,c;i<=n;fr[ch[x][c]]=x,x=ch[x][c],i++)
        if(!ch[x][c=a[i]]) ch[x][c]=++node_cnt,frv[ch[x][c]]=c;
    return s[x]|=v;
}
inline int getfail()
{
    while(!q.empty()) q.pop();
    rep(i,0,1)
    {
        int &c=ch[1][i];
        if(c) fa[c]=1,q.push(c);
        else c=1;
    }
    while(!q.empty())
    {
        int x=q.front();
        s[x]|=s[fa[x]],q.pop();
        rep(i,0,1)
        {
            int &y=ch[x][i],f=fa[x],c=ch[f][i];
            if(y) fa[y]=c,q.push(y);else y=c;
        }
    }
    return 0;
}
inline int gett(int x,int ans=0)
{
    for(int y=x;fr[x];x=fr[x]) ans|=s[y=ch[y][frv[x]^1]];
    return ans;
}
inline int upd(int &x,int y) { return x+=y,(x>=mod?x-=mod:0); }
int main()
{
    int m=inn(),n=inn();node_cnt=1;
    rep(qwq,1,m)
    {
        scanf("%s",str+1);int l=(int)strlen(str+1);
        rep(i,1,l) a[i]=str[i]-'0';ins(a,l,1<<(qwq-1));
        rep(i,1,l) a[i]=!a[i];
        rep(i,1,l/2) swap(a[i],a[l-i+1]);
        ins(a,l,1<<(qwq-1));
    }
    getfail(),dp[0][0][1]=1;
    int nc=node_cnt,all=(1<<m)-1;
    rep(i,0,n-1) rep(j,0,all) rep(k,1,nc)
        if(dp[i][j][k]) for(int t=0,p;t<=1;t++)
            p=ch[k][t],upd(dp[i+1][j|s[p]][p],dp[i][j][k]);
    int ans=0;
    rep(i,1,nc)
    {
        int t=gett(i);
        rep(j,0,all) if((j|t)==all) upd(ans,dp[n][j][i]);
    }
    return !printf("%d\n",ans);
}


资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值