[LA 3942] Remember the Word

Link:

LA 3942 传送门

Solution:

感觉自己字符串不太行啊,要加练一些蓝书上的水题了……

 

$Trie$+$dp$

转移方程:$dp[i]=sum\{ dp[i+len(x)+1]\} (x为从第i位开始的字符串的前缀)$

计算一个字符串前缀的多模式匹配在$Trie$树上跑一遍就行啦!

Code:

#include <bits/stdc++.h>

using namespace std;
const int MAXN=4e5+10,MOD=20071027;
bool vis[MAXN];
char s[MAXN],tmp[MAXN];
int T,n,ch[MAXN][30],dp[MAXN],l,len,cnt=0,rt=0;

int main()
{
    while(~scanf("%s",s+1))
    {
        memset(ch,0,sizeof(ch));memset(dp,0,sizeof(dp));
        memset(vis,false,sizeof(vis));
        
        T++;len=strlen(s+1);
        scanf("%d",&n);cnt=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",tmp+1);l=strlen(tmp+1);
            int cur=rt;
            for(int j=1;j<=l;j++)
            {
                if(!ch[cur][tmp[j]-'a']) 
                    ch[cur][tmp[j]-'a']=++cnt;
                cur=ch[cur][tmp[j]-'a'];
            }
            vis[cur]=true;
        }
        
        dp[len+1]=1;
        for(int i=len;i>=1;i--)
        {
            int cur=rt;
            for(int j=i;j<=len;j++)
            {
                if(!ch[cur][s[j]-'a']) break;
                cur=ch[cur][s[j]-'a'];
                if(vis[cur]) (dp[i]+=dp[j+1])%=MOD;
            }
        }
        printf("Case %d: %d\n",T,dp[1]);
    }
    return 0;
}

 

posted @ 2018-06-30 19:54  NewErA  阅读(243)  评论(0编辑  收藏  举报