[HNOI2004]L语言

Description:

给出n个串和m个串,
分别求出这m个串能被n个串中的串拼出的最长前缀
注意:一定是拼出,串不能重叠!!!

Hint:

\(n,m<=20\)
$ len_n<=10 ,len_m<=10^6 $

Solution:

一开始看错题了,还有60多分.....
正解直接dp一下就行了

#include<bits/stdc++.h>
using namespace std;
const int mxn=1e7+5;
int f[mxn];
char str[mxn],p[80],vis[mxn];
queue<int > q;

namespace Trie {
    int tot,fail[mxn],val[mxn];
    int t[mxn][26];
    void ins(char *s) {
        int len=strlen(s),u=0;
        for(int i=0;i<len;++i) {
            if(!t[u][s[i]-'a']) t[u][s[i]-'a']=++tot;
            u=t[u][s[i]-'a'];
        }
        val[u]=len;
    };
    void build() {
        for(int i=0;i<26;++i) 
            if(t[0][i]) fail[t[0][i]]=0,q.push(t[0][i]);
        while(!q.empty()) {
            int u=q.front(); q.pop();
            for(int i=0;i<26;++i) {
                if(t[u][i]) fail[t[u][i]]=t[fail[u]][i],q.push(t[u][i]);
                else t[u][i]=t[fail[u]][i]; 
            }
        }	
    };
    int query(char *s) {
        int len=strlen(s),u=0,ans=0,mi=0; 
		for(int i=0;i<=len;++i) f[i]=0;
		f[0]=1;
        for(int i=0;i<len;++i) {
            u=t[u][s[i]-'a']; vis[i]=0; 
            for(int v=u;v;v=fail[v]) 
                if(val[v]) {
                    f[i+1]|=f[i-val[v]+1];
                }
        }
        for(int i=len;i>=0;--i) 
			if(f[i]) return i;
    };
}
using namespace Trie;

int main()
{
    int n,m; scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) 
        scanf("%s",p),ins(p);
    build();	
    while(m--) {
        scanf("%s",str); 
        printf("%d\n",query(str));
    }
    return 0;
}
posted @ 2019-02-16 12:49  cloud_9  阅读(96)  评论(0编辑  收藏  举报