ac自动机

本文介绍了一种基于AC自动机的状态压缩动态规划算法,用于解决字符串匹配问题中的最小编辑距离求解。通过构建AC自动机加速模式串的查找过程,并结合动态规划策略优化搜索路径,实现对输入字符串进行高效匹配及最小化编辑操作。

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

////HDU 2457
/////f[u]=r,r包含在u的后缀中
/////last[u]=r,r包含在u的后缀中,并且是一个单词
////每增加一个字母,状态转移一次
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int inf=1<<25;
const int MN=55*22+100;
const int SZ=30;
int ch[MN][SZ];int val[MN];
int sz,tot;
void init(){tot=1;sz=4;memset(ch[0],0,sizeof(ch[0]));val[0]=0;}
int idx(char c){
    if(c=='A')return 0;
    else if(c=='G')return 1;
    else if(c=='C')return 2;
    else return 3;
}
void Ins(char *s,int v){
    int u=0,n=strlen(s);
    //printf("%s\n",s);
    for(int i=0;i<n;i++){
        int c=idx(s[i]);
        if(!ch[u][c]){
            memset(ch[tot],0,sizeof(ch[tot]));val[tot]=0;
            ch[u][c]=tot++;
        }
        u=ch[u][c];
        //printf("%d ",u);
    }//printf("\n");
    val[u]=v;
}
int f[MN],last[MN];
int getFail(){
    queue<int> qq;
    f[0]=0;last[0]=0;
    for(int c=0;c<sz;c++){
        int u=ch[0][c];
        if(u){f[u]=0;last[u]=0;qq.push(u);}
    }
    while(!qq.empty()){
        int r=qq.front();qq.pop();
        for(int c=0;c<sz;c++){
            int u=ch[r][c];
            if(!u){
                ch[r][c]=ch[f[r]][c];continue;
            }
            qq.push(u);
            f[u]=ch[f[r]][c];
            last[u]=val[f[u]]?f[u]:last[f[u]];
            val[u]|=val[f[u]];
        }
    }
}
int dp[MN][1100],len;
char ss[30],tt[1000+100];
int dfs(int u,int x){
    if(x==len)return dp[u][x]=0;
    if(dp[u][x]!=-1)return dp[u][x];
    int ans=inf;
    for(int c=0;c<sz;c++){
        int v=ch[u][c];
        if(val[v])continue;
        if(c==idx(tt[x+1])){
            ans=min(ans,dfs(v,x+1));
        }
        else {
            ans=min(ans,dfs(v,x+1)+1);
        }
    }
    return dp[u][x]=ans;
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    int n,cas=1;
    while(scanf("%d",&n)!=EOF,n){
        init();
        for(int i=0;i<n;i++){
            scanf("%s",ss);
            Ins(ss,1);
        }
        getFail();
        scanf("%s",tt+1);
        len=strlen(tt+1);
        memset(dp,-1,sizeof(dp));
        dfs(0,0);
        printf("Case %d: ",cas++);
        if(dp[0][0]==inf){
            printf("-1\n");
        }
        else printf("%d\n",dp[0][0]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值