luogu P4022 [CTSC2012]熟悉的文章
作者:互联网
题面传送门
看到字符串子串匹配啪的一下很快啊一个SAM扔上去了
先把\(M\)个串的SAM建出来,发现其实不用广义SAM,隔一个#
插就好了。
然后对于每个询问串就可以在SAM上先刨除每个\(i\)结尾在模式串中最长匹配多少。
显然L有单调性所以直接二分然后\(O(n^2)\)dp就可以得到答案了。
又有显然的每个点最左边能匹配的单调不降,所以可以上单调队列维护当前\(dp_i-i\)就可以做到\(O(nlogn)\)了。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 1100000
#define M 300000
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,Q[N+5],H,T,dp[N+5],L[N+5],k,l,r,mid;char S[N+5];
namespace SAM{
int cnt=1,son[N+5][3],link[N+5],len[N+5],p,La=1,q;I void Ins(char c){
c^'#'?c-='0':c=2;;p=La;La=++cnt;len[La]=len[p]+1;while(p&&!son[p][c]) son[p][c]=La,p=link[p];if(!p){link[La]=1;return;}
q=son[p][c];if(len[q]==len[p]+1)link[La]=q;else{
link[++cnt]=link[q];link[q]=link[La]=cnt;len[cnt]=len[p]+1;memcpy(son[cnt],son[q],sizeof(son[q]));
while(p&&son[p][c]==q) son[p][c]=cnt,p=link[p];
}
}
I int check(int mid){
RI i;H=1;T=0;for(i=1;i<=k;i++){
if(i>=mid){while(H<=T&&dp[Q[T]]-Q[T]<=dp[i-mid]-(i-mid)) T--;Q[++T]=i-mid;}while(H<=T&&Q[H]<i-L[i]) H++;dp[i]=dp[i-1];H<=T&&(dp[i]=max(dp[i],dp[Q[H]]+(i-Q[H])));
}/*printf("%d %d\n",mid,dp[k]);*/return dp[k]>=k*0.9;
}
I void Solve(){
RI i;scanf("%s",S+1);k=strlen(S+1);p=1;q=0;for(i=1;i<=k;i++) {while(p&&!son[p][S[i]-'0']) p=link[p],q=len[p];if(!p) p=1,q=0;else p=son[p][S[i]-'0'],q++;L[i]=q;/*printf("%d %d\n",p,q);*/}
l=1;r=k+1;while(l+1<r) mid=l+r>>1,(check(mid)?l:r)=mid;printf("%d\n",l);
}
}
int main(){
freopen("1.in","r",stdin);
RI i;scanf("%d%d",&n,&m);while(m--)for(scanf("%s",S+1),SAM::Ins('#'),k=strlen(S+1),i=1;i<=k;i++) SAM::Ins(S[i]);while(n--)SAM::Solve();
}
标签:cnt,P4022,La,luogu,len,son,link,CTSC2012,define 来源: https://www.cnblogs.com/275307894a/p/15546590.html