说在前面
本来以为要建AC自动机,结果发现网上的题解都…直接上trie就可以了= =???
复杂度明明爆炸啊…
题目
题面
一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。 我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。 例如字典D中包括单词{is, name, what, your},则文章whatisyourname是在字典D下可以被理解的,因为它可以分成4个单词:what, is, your, name,且每个单词都属于字典D。同理,文章‘whatisyouname’ 在字典D下不能被理解,不过这段文章的一个前缀whatis是可以被理解的。
现在给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。 并给出其在字典D下能够被理解的最长前缀的位置。
输入输出格式
输入格式:
输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。 之后的n行每行描述一个单词,再之后的m行每行描述一段文章。 其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1e6
输出格式:
对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置
解法
建好trie直接跑dp
令( bool ) dp[i]表示可以理解长度为i的前缀
如果当前dp[i]为true,就进trie去匹配,匹配到一个末尾节点就更新dp,刷表法
下面是自带大常数的代码
/**************************************************************
Problem: 1212
User: Izumihanako
Language: C++
Result: Accepted
Time:516 ms
Memory:2872 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int N , M , lena , maxlen , ans ;
bool dp[1024*1024+5] ;
char ss[25][25] , a[1024*1024+5] ;
struct Node{
bool isend ;
char c ;
Node *ch[26] ;
}*root ;
void newNode( Node *&nd ){
nd = new Node() ;
nd->isend = false ;
memset( nd->ch , 0 , sizeof( nd->ch ) ) ;
}
void Insert( char *ts ){
int len = strlen( ts ) ;
maxlen = max( maxlen , len ) ;
Node *nd = root ;
for( int i = 0 ; i < len ; i ++ ){
int nxt = ts[i] - 'a' ;
if( !nd->ch[nxt] ){
newNode( nd->ch[nxt] ) ;
nd->ch[nxt]->c = ts[i] ;
}
nd = nd->ch[nxt] ;
}
nd->isend = true ;
}
inline void update( int pos ){
Node *nd = root ;
for( ; ; ){
//printf( "address(%d-[%c]) pos(%d) \n" , nd , nd->c , pos ) ;
int nxt = a[pos] - 'a' ;
if( !nd->ch[nxt] ) return ;
nd = nd->ch[nxt] ; pos ++ ;
if( nd->isend ) dp[pos] = true ;
}
}
void solve(){
for( register int i = 1 , j , tmp ; i <= M ; ++ i ){
scanf( "%s" , a ) ; lena = strlen( a ) ;
dp[0] = 1 ; ans = 0 ;
for( j = 0 , tmp = 0 ; j < lena ; ++ j ){
if( dp[j] ){
update( j ) ;
tmp = 0 ; ans = j ;
} else {
++ tmp ;
if( tmp == maxlen ) break ;
}
}
printf( "%d\n" , dp[lena] ? lena : ans ) ;
memset( dp , 0 , ( lena + 1 ) * sizeof( bool ) ) ;
}
}
int main(){
newNode( root ) ; root->c = 0 ;
scanf( "%d%d" , &N , &M ) ;
for( int i = 1 ; i <= N ; i ++ ){
scanf( "%s" , ss[i] ) ;
Insert( ss[i] ) ;
}
solve() ;
}