[HNOI2004] L语言

洛谷 P2292 传送门

bzoj 1212 传送门

建trie图,开一个数组f[k]记录前缀text[1~k]能否被理解。

在trie图上匹配的时候,考虑更新f[k]数组。

若匹配到了模式串结尾( ed[ j ]不为0 )且这个模式串开头位置的前面都能被理解( f[ i - ed[ j ] ] = 1 ),

那么模式串结尾位置的前面也都能被理解。

所以我们需要皮一下,记录终止位置的数组ed[]顺便记录一下在这个位置终止的模式串的长度。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 
 7 int n,m;
 8 int s[205][30],sz;
 9 int fal[205],ed[205];
10 char str[15];
11 char text[1000005];
12 int f[1000005];
13 
14 void ins()
15 {
16     scanf("%s",str+1);
17     int l=strlen(str+1);
18     int p=0;
19     for(int i=1;i<=l;i++)
20     {
21         int c=str[i]-'a'+1;
22         if(!s[p][c])s[p][c]=++sz;
23         p=s[p][c];
24     }
25     ed[p]=l;
26 }
27 
28 queue<int>qq;
29 
30 void build()
31 {
32     qq.push(0);
33     while(!qq.empty())
34     {
35         int p=qq.front();
36         qq.pop();
37         for(int i=1;i<=26;i++)
38         {
39             int lf=(!p)?0:s[fal[p]][i];
40             if(s[p][i])fal[s[p][i]]=lf,qq.push(s[p][i]);
41             else s[p][i]=lf;
42         }
43     }
44 }
45 
46 int main()
47 {
48     scanf("%d%d",&n,&m);
49     for(int i=1;i<=n;i++)ins();
50     build();
51     for(int i=1;i<=m;i++)
52     {
53         scanf("%s",text+1);
54         int l=strlen(text+1);
55         memset(f,0,sizeof(f));
56         f[0]=1;
57         int ans=0,p=0;
58         for(int i=1;i<=l;i++)
59         {
60             int c=text[i]-'a'+1;
61             p=s[p][c];
62             for(int j=p;j;j=fal[j])
63             {
64                 if(ed[j]&&f[i-ed[j]])
65                 {
66                     f[i]=1;
67                     ans=max(ans,i);
68                     break;
69                 }
70             }
71         }
72         printf("%d
",ans);
73     }
74     return 0;
75 }
原文地址:https://www.cnblogs.com/eternhope/p/9700443.html