[DP+AC自动机] BZOJ1212: [HNOI2004]L语言

直接 DP fi 表示前 i 个是否合法。fi|=filen(aj)(s[ilen(aj)+1]=aj)
AC 自动机加速转移的匹配过程。

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100005;
int a[maxn];
struct node{
    node *ch[26],*fail,*last; vector<int> lst;
    node(node* son=NULL){ for(int i=0;i<=25;i++) ch[i]=son; lst.clear(); fail=last=son; }
} nil, *null=&nil, *root=null;
typedef node* P_node;
void Insert(char *now,P_node &p,int _len){
    if(p==null) p=new node(null);
    if((*now)==0){ p->lst.push_back(_len); return; }
    Insert(now+1,p->ch[(*now)-'a'],_len);
}
void Build_AC(){
    static queue<P_node> Q;
    root->fail=root->last=root;
    for(int i=0;i<=25;i++) if(root->ch[i]!=null){
        P_node v=root->ch[i]; Q.push(v);
        v->fail=v->last=root;
    } else root->ch[i]=root;
    while(!Q.empty()){
        P_node p=Q.front(); Q.pop();
        for(int i=0;i<=25;i++) if(p->ch[i]!=null){
            P_node v=p->ch[i]; Q.push(v);
            v->fail=p->fail->ch[i]; v->last=(v->fail->lst.empty()?v->fail->last:v->fail);
        } else p->ch[i]=p->fail->ch[i];
    }
}
char st[1100000];
int n,m,f[1100000],ans;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",st), Insert(st,root,strlen(st)); 
    Build_AC();
    while(m--){
        scanf("%s",st); int len=strlen(st);
        for(int i=0;i<=len;i++) f[i]=0; f[0]=1;
        P_node p=root; ans=0;
        for(int i=1;i<=len;i++){
            p=p->ch[st[i-1]-'a'];
            for(P_node t=p;t!=root;t=t->last)
             for(int j=0;j<t->lst.size();j++) f[i]|=f[i-t->lst[j]];
            if(f[i]) ans=i;
        }
        printf("%d\n",ans); 
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值