[HNOI2004][bzoj1212] L language[Trie+dp]

topic

portal

ideas

no aftereffect

Obviously, no matter how a certain prefix is ​​understood, if it can be understood, then the previous decision is equivalent to the latter decision

So this question can be DP

DP equation

Let $dp[i]$ denote whether the prefix i can be understood

Then, obviously the state transition equation is:

$dp[i]=dp[i]||dp[j];;(s[j+1...i]\in D)$

That is to say, now our problem is transformed into: find all the words that can be matched by the i-th forward number

Because the direction and way of counting forward is unique, we think of a string data structure: $Trie$

$Trie$

A very common idea is to insert all words into $trie$, and then use this forward substring to match words

But there is a problem with this: we are matching from a certain deep position of $trie$ to the root, and there may be multiple such start nodes

The root cause of this problem is that we use a suffix to match words, but our $trie$ is saved as a prefix

So, we just need to change the way $trie$ is saved from prefix to suffix

We reverse all words and insert them into $trie$

When looking for $dp[i]$, start from $s[i]$ and move forward, $trie$ starts from the root node, goes down, and goes to the end of a word (in fact, it is the beginning of the word after the reverse) , use this position to update $dp[i]$

Total time efficiency upper limit:

$O\left(m\left(10strlen(s)+O\left(Trie\right)\right)\right)=O\left(2\ast10^8\right)$

But generally it can't reach so much. The last point of my code is 272ms, which is still very stable.

It's really not possible, give oxygen to the evaluation machine [fog]

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{//trie节点
    int num,son[27];
    node(){num=0;memset(son,0,sizeof(son));}
}x[210];
int n,m,dp[1000010],cnt;char a[1000010];
void add(char s[20]){//插入单词
    int len=strlen(s),cur=0,i;
    for(i=len-1;i>=0;i--){
        if(!x[cur].son[s[i]-'a']) x[cur].son[s[i]-'a']=++cnt;
        cur=x[cur].son[s[i]-'a'];
    }
    x[cur].num++;
}
void check(char s[],int pos){
    int cur=0,i,flag=0;
    for(i=pos-1;i>=0;i--){
        if(!x[cur].son[s[i]-'a']) break;
        cur=x[cur].son[s[i]-'a'];if(x[cur].num&&dp[i]) flag=1;
    }
    dp[pos]=flag;
}
int main(){
    scanf("%d%d",&n,&m);int i,len,l,j,ans;char s[20];
    for(i=1;i<=n;i++) scanf("%s",s),add(s);
    for(l=1;l<=m;l++){
        scanf("%s",a);memset(dp,0,sizeof(dp));
        dp[0]=1;len=strlen(a);ans=0;
        for(i=1;i<=len;i++){
            check(a,i);
            if(dp[i]) ans=max(i,ans);
        }
        printf("%d\n",ans);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324689076&siteId=291194637