题意:
如今,在建筑的墙面上或者篱笆桩的表面上涂上一些广告,是一种新的吸引眼球的方法。
现在,小G 运营的一家小公司,决定也试着这样做做广告。小G 在他的篱笆桩上腾出了一些地方供广告使用。每一个篱笆桩都是一个水平的1*1*L 的4 棱柱,其中有一个1*L 的面是可以做广告的。1*L 的面上划出了L 个1*1 的小正方形(更具体地说是连续L 个水平排列的正方形),每个正方形内写上一个字母。
时间久了,广告做多了难免会出现一些比较麻烦的情况,比如计划改变或者制作出错,因此小G 的仓库里面积累了好多没有用的,上面已经写上L 个字母的篱笆桩。(所有的篱笆桩的大小都是一样的,他们唯一的区别仅仅在于上面写了什么字母)。
小G 决定对于这些篱笆桩进行重新利用,并且有了一些新的想法。
如果将这些篱笆桩竖直的叠放起来,并且依次从左往右,对于每一个篱笆桩顺次从上到下读出上面的字母,那么我们可以得到一些新的比较长的单词,如下图:
这些新的单词能满足小G 的一些新的需要。当然,基于美学考虑,小G 是不允许你删改篱笆桩上已经写上的字母的。
我们更具体地描述这个过程。我们将K 个长度为L 的篱笆桩叠在一起,可以得到一个写有K行L 列共K*L 个字母的面,每一个字母都在对应的唯一的格子里。我们从左上角开始依次向下读出每一个字母可以得到一个字母的序列,比如上图中的这个例子,那么我们读出的结果就是“TOEIIZENITKN”。如果,这个串中有我们所需要的单词,那么显然我们只需要将一些格子刷白,就可以得到我们所需要的了。举个例子,比如小G 想要给圣彼得堡的足球队泽尼特队做个广告,那么很显然只要按照上图中的做法就可以达到小G 想要的效果了。
现在小G已经想好了要做怎样的广告,同时也提供给你了小G仓库中的篱笆桩的类型的描述,你可以认为每一种类型的篱笆桩都是有无数个的。现在小G 想知道至少需要多少个篱笆桩叠起来才可以做出小G 想要的广告。
N,L≤100
分析:
注意,目标串必须是子串,不是子序列。(考试时就这样读错题了)
这题暴力可过…..
我们可以从小到大枚举答案所需的篱笆桩个数,我们发现,对于一个固定的答案k,一个篱笆桩若要能与答案串匹配,则s[j] = tar[x],s[j+1] = tar[x+k],s[j+2] = tar[x + k + k]…其中s为篱笆桩字符串,tar为广告串,
x≤k
,且要能一直匹配到
len(tar)≤x+k∗n
。所以我们枚举答案串开头坐标为拼完篱笆桩后的(i,j),然后剩下的暴力匹配…..YY一下…
代码略丑(v[i][j]为广告串在答案为ans的情况下从广告串第i位开头,在第j列能匹配的篱笆桩的编号)
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 150;
char s[N][N],tar[2 * N];
int n,m,len,a[2 * N],ida,flag,ans,v[2 * N][N];
bool find;
int main() {
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i ++) {
scanf(" %s",&s[i]);
int cur = strlen(s[i]);
for (int j = cur;j;j --) s[i][j] = s[i][j - 1];
}
scanf(" %s",&tar);
len = strlen(tar);
for (int i = len;i;i --) tar[i] = tar[i - 1];
for (ans = 1;ans <= len;ans ++) {
memset(v,0,sizeof(v));
for (int i = 1;i <= ans;i ++) {
for (int j = 1;j <= m;j ++) {
for (int k = 1;k <= n;k ++) {
int x,y;
for (x = i,y = j;x <= len,y <= m;x += ans,y ++) {
if (s[k][y] != tar[x]) break;
}
if (x > len) {
v[i][j] = k;
break;
}
}
}
}
int flag = 1;
for (int j = 1;j <= m;j ++) {
for (int i = 1;i <= ans;i ++) {
int flag = 1;
for (int k = 1;k <= i;k ++) {
if (!v[k][j]) {
flag = 0;
break;
}
else a[i - k + 1] = v[k][j];
}
if (!flag) break;
for (int k = i + 1;k <= ans;k ++) {
if (!v[k][j + 1]) {
flag = 0;
break;
}
else a[ans - (k - i) + 1] = v[k][j + 1];
}
if (flag) {
find = true;
break;
}
}
if (find) break;
}
if (find) break;
}
if (!find) printf("-1");
else {
printf("%d\n",ans);
for (int i = ans;i;i --) printf("%d ",a[i]);
}
}