BZOJ4460 : [Jsoi2013]广告计划
首先预处理出$f[i][j]$表示第$i$位是字符$j$的字符串集合。
考虑枚举答案$n$,那么模式串中模$n$相同的字符都要按顺序在同一行出现。
设$g[i][j]$表示第$i$列开始出现模$n$为$j$的那些字符是否有可能,可以通过bitset取交实现。
然后枚举模式串出现的列$x$进行贪心匹配,一旦失配则接下来都应该匹配$x+1$。
时间复杂度$O(\frac{n^4}{64})$。
#include<cstdio> #include<cstring> #include<bitset> using namespace std; const int N=210; int n,L,m,i,j;char s[N];bitset<105>f[N][26],tmp,full;bool g[N][N]; inline bool check(int n){ int i,j,k,o; for(i=1;i<=L;i++)for(j=1;j<=n;j++){ tmp=full; for(k=j,o=i;k<=m;k+=n,o++)if(o>L)tmp.reset();else tmp&=f[o][s[k]]; g[i][j]=tmp.count()>0; } for(i=1;i<=L;i++){ for(j=1;j<=n;j++)if(!g[i][j])break; if(j>n)return 1; for(;j<=n;j++)if(!g[i+1][j])break; if(j>n)return 1; } return 0; } int main(){ scanf("%d%d",&n,&L); for(i=1;i<=n;i++){ scanf("%s",s+1); full[i]=1; for(j=1;j<=L;j++)f[j][s[j]-'a'][i]=1; } scanf("%s",s+1); m=strlen(s+1); for(i=1;i<=m;i++)s[i]-='a'; for(i=1;i<=m;i++)if(check(i))break; return printf("%d",i),0; }