bzoj1212: [HNOI2004]L语言
这又是什么神题啊。
这题一眼AC机。然后呢企鹅也是这么想的。
写完发现企鹅看错题了。然后其实建字典树就行了。
弄个v数组表示能否匹配到第i个位置。然后因为字典里的串很短,就判一下前面L(表示字典里最长那个串的长度)个位置能否匹配,可以的话就把那个位置后一位到当前位置抠出来,去字典树找有没有。
复杂度应该是O(m*len*L*L)蛮大的。
其实没这么可怕,因为不是每个位置都可以匹配到,然后匹配到一个OK就可以break了,还有,只要连续L个不能匹配,答案就出来了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; char ss[1100000]; struct Trie { int c,w[30]; Trie() { c=0; memset(w,0,sizeof(w)); } }tr[310];int trlen; void maketree() { int now=0,len=strlen(ss+1); for(int i=1;i<=len;i++) { int x=ss[i]-'a'+1; if(tr[now].w[x]==0)tr[now].w[x]=++trlen; now=tr[now].w[x]; } tr[now].c=1; } bool findchuan(int l,int r) { int now=0; for(int i=l;i<=r;i++) { int x=ss[i]-'a'+1; if(tr[now].w[x]==0)return false; now=tr[now].w[x]; } if(tr[now].c==0)return false; return true; } bool v[1100000]; int main() { int n,m,L=0; scanf("%d%d",&n,&m);trlen=0; for(int i=1;i<=n;i++) { scanf("%s",ss+1); maketree(); int len=strlen(ss+1);L=max(L,len); } while(m--) { scanf("%s",ss+1); int len=strlen(ss+1); memset(v,false,sizeof(v)); int ans=0; for(int i=1;i<=len;i++) { bool bk=false; if(i<=L) { bk=true; v[i]=findchuan(1,i); if(v[i]==true)ans=i; } if(v[i]==true)continue; for(int j=max(1,i-L);j<i;j++) { if(v[j]==true) { bk=true; v[i]=findchuan(j+1,i); if(v[i]==true){ans=i;break;} } } if(bk==false)break; } printf("%d\n",ans); } return 0; }
pain and happy in the cruel world.