[BZOJ 1212] L语言

Link:

BZOJ 1212 传送门

Solution:

看到字符串的多模式匹配,正解一般就是Trie树/AC自动机

 

此题由于每个模式串长度都很小,于是直接在Trie树上暴力就行了

先把所有模式串建一颗Trie树,

用$DP[i]$表示能否匹配到第$i$个字符,如果能,则从第$i+1$位开始继续从根开始匹配,查看能否拓展答案

 

上述偏暴力的做法复杂度在$O(4*10^8)$左右,

好像还有一种用AC自动机+状压DP的做法能降到$O(10^6)$,后面再填吧

Code:

#include <bits/stdc++.h>

using namespace std;

const int MAXN=1e6+10;
struct trie
{
    int ch[30];
    bool flag;
}tr[300];

int n,m,dp[MAXN],cnt=1;
char s[MAXN];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)  //建立Trie树
    {
        scanf("%s",s);
        int cur=1,len=strlen(s);
        for(int j=0;j<len;j++)
        {
            if(!tr[cur].ch[s[j]-'a']) tr[cur].ch[s[j]-'a']=++cnt;
            cur=tr[cur].ch[s[j]-'a'];
        }
        tr[cur].flag=true;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);memset(dp,0,sizeof(dp));
        int len=strlen(s);dp[0]=1;
        for(int j=0;j<len;j++)
        {
            if(!dp[j]) continue;
            int cur=1,k=j;
            while(tr[cur].ch[s[k]-'a'])
            {
                cur=tr[cur].ch[s[k++]-'a'];
                if(tr[cur].flag) dp[k]=1;
            }
        }
        for(int j=len;j>=0;j--)
            if(dp[j]){printf("%d\n",j);break;} 
    }
    return 0;
}

Review:

看到多模式匹配,往Trie+AC自动机上想就对了

posted @ 2018-06-01 10:33  NewErA  阅读(238)  评论(0编辑  收藏  举报