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;
}

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值