[HNOI2004] L语言
建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\n",ans); 73 } 74 return 0; 75 }