N行,每行一個整數,表示這篇做文的Lo 值。ios
輸入文件不超過1100000字節優化
注意:題目有改動,可識別的長度不小於90%便可,而不是大於90% spa
好題!code
先對標準做文庫建出廣義SAM,把每一個做文串在SAM上匹配,求出每一位以前最長出現過子串長度$s[i]$;orm
顯然沒有什麼好辦法直接求L,考慮二分答案判斷是否可行;blog
設當前二分值爲$mid$,$f[i]$表示前$i$位最長的熟悉長度,則易得DP方程:$f[i]=max\{f[j]+i-j\}$,決策區間就是$[i-s[i],i-mid]$;隊列
顯然$i-s[i]$單調不降,因此能夠用單調隊列優化到$O(n)$ip
最後判一下比例是否大於$90\%$便可。string
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std; 10 typedef long long ll; 11 typedef double db; 12 int n,m,l,r,ans,len,tot=1,last,rt=1,son[2200001][2],fa[2200001],mx[2200001],s[1100001],q[1100001],f[1100001]; 13 char st[1100001]; 14 void extend(int ch){ 15 int p=last,np=++tot; 16 mx[np]=mx[p]+1; 17 for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np; 18 if(!p)fa[np]=rt; 19 else{ 20 int q=son[p][ch]; 21 if(mx[q]==mx[p]+1)fa[np]=q; 22 else{ 23 int nq=++tot; 24 mx[nq]=mx[p]+1; 25 memcpy(son[nq],son[q],sizeof(son[q])); 26 fa[nq]=fa[q]; 27 fa[q]=fa[np]=nq; 28 for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq; 29 } 30 } 31 last=np; 32 } 33 void pre(char *st,int len){ 34 int nw=rt,tmp=0; 35 for(int i=1;i<=len;i++){ 36 if(son[nw][st[i]-'0']){ 37 nw=son[nw][st[i]-'0']; 38 tmp++; 39 }else{ 40 for(;nw&&!son[nw][st[i]-'0'];nw=fa[nw]); 41 if(!nw){ 42 nw=rt; 43 tmp=0; 44 }else{ 45 tmp=mx[nw]+1; 46 nw=son[nw][st[i]-'0']; 47 } 48 } 49 s[i]=tmp; 50 } 51 } 52 bool check(int k){ 53 int L=1,R=0; 54 for(int i=1;i<=len;i++){ 55 f[i]=f[i-1]; 56 if(i<k)continue; 57 for(;L<=R&&f[q[R]]-q[R]<f[i-k]-i+k;R--); 58 q[++R]=i-k; 59 for(;L<=R&&q[L]<i-s[i];L++); 60 if(L<=R)f[i]=max(f[i],f[q[L]]-q[L]+i); 61 } 62 return f[len]*10>=len*9; 63 } 64 int main(){ 65 scanf("%d%d",&n,&m); 66 for(int i=1;i<=m;i++){ 67 scanf("%s",st+1); 68 len=strlen(st+1); 69 last=rt; 70 for(int j=1;j<=len;j++){ 71 extend(st[j]-'0'); 72 } 73 } 74 for(int i=1;i<=n;i++){ 75 scanf("%s",st+1); 76 len=strlen(st+1); 77 pre(st,len); 78 l=ans=0,r=len; 79 while(l<=r){ 80 int mid=(l+r)/2; 81 if(check(mid))ans=mid,l=mid+1; 82 else r=mid-1; 83 } 84 printf("%d\n",ans); 85 } 86 return 0; 87 }