[HNOI2004] L语言

AC自动机+DP

AC自动机NOIP考不考啊。。。

在AC自动机上做个DP。

设状态f[i]表示最远可以匹配到的i,然后在AC自动机上找就行了。

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1100005;
int f[N],len[205];
struct AC {
    char s[N];
    int val[205],tr[205][26],tot,fail[205];
    void insert(char *ch) {
        int l=strlen(ch+1),p=0;
        for(int i=1;i<=l;i++) {
            if(!tr[p][ch[i]-'a']) tr[p][ch[i]-'a']=++tot;
            p=tr[p][ch[i]-'a'];
        }
        val[p]=1;
        len[p]=l;
    }
    void getfail() {
        queue<int>q;
        for(int i=0;i<26;i++) if(tr[0][i])
            q.push(tr[0][i]);
        while(!q.empty()) {
            int u=q.front();q.pop();
            for(int i=0;i<26;i++) {
                if(!tr[u][i]) tr[u][i]=tr[fail[u]][i];
                else fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]);
            }
            val[u]|=val[fail[u]];
        }
    }
    void query(char *ch) {
        int l=strlen(ch+1),p=0;
        for(int i=1;i<=l;i++) {
            p=tr[p][ch[i]-'a'];
            if(val[p]) {
                int tp=p;
                while(tp) f[i]|=f[i-len[tp]],tp=fail[tp];
            }
        }
    }
}ac;
int n,m;
int main() {
    scanf("%d%d",&n,&m);
    char ch[N];
    for(int i=1;i<=n;i++) {
        scanf("%s",ch+1);
        ac.insert(ch);
    }
    ac.getfail();
    for(int i=1;i<=m;i++) {
        scanf("%s",ch+1);
        memset(f,0,sizeof f);
        f[0]=1;
        ac.query(ch);
        int len=strlen(ch+1);
        for(int j=1;j<=len;j++) if(!f[j]) {
            printf("%d\n",j-1);break;
        }
        
    }
    return 0;
}
L语言

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9787101.html