【题目链接】:
【题意】:
给出n个模式串。请问文本串是由多少个模式串组成的。
【题解】:
当我学完AC自动机后,发现这个题目也太简单了吧.
不过当时我还是不会,后来看了看洛谷有位大佬的题解。
简直醍醐灌顶。纯Trie树也能写出这个题来。
就是把对应的位置标记上,好比dp的转移。
这个转移是,开一个Mark数组,看看文本串中哪个位置能通过这些模式串匹配出来的。
然后一直转移即可。
【代码】:
1 //L语言 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N = 3e4 ; 7 const int M = 3e4 * 26; 8 const int LEN = 2e6; 9 int Son[M][26],idx; 10 bool cnt[M]; 11 bool Mark[LEN]; 12 char s[LEN]; 13 int n,m; 14 void Insert(){ 15 int p = 0 ; 16 for(int i=0;s[i];i++){ 17 int t = s[i]-'a'; 18 if( !Son[p][t] ) Son[p][t] = ++idx; 19 p = Son[p][t]; 20 } 21 cnt[p] = true; 22 } 23 void Query(){ 24 memset( Mark , false , sizeof Mark ); 25 int p = 0 ; 26 for(int i=0;s[i];i++){ 27 int t = s[i] - 'a'; 28 if ( !Son[p][t] ) break; 29 p = Son[p][t]; 30 if( cnt[p] ) Mark[i] = true; 31 } 32 33 int ans = 0 ; 34 for(int i=0 ; s[i] ; i++ ){ 35 if( !Mark[i] ) continue; 36 else ans = i+1 ; 37 p = 0 ; 38 for(int j=i+1;s[j];j++){ 39 int t = s[j] - 'a'; 40 if ( !Son[p][t] ) break; 41 p = Son[p][t]; 42 if( cnt[p] ) Mark[j] = true; 43 } 44 } 45 printf("%d\n",ans); 46 } 47 int main() 48 { 49 scanf("%d%d",&n,&m); 50 for(int i=0;i<n;i++){ 51 scanf("%s",s); 52 Insert(); 53 } 54 for(int i=0;i<m;i++){ 55 scanf("%s",s); 56 Query(); 57 } 58 return 0; 59 }