1. select some indices i1,i2,...,ik such that 1≤i1<i2<...<ik<|p| and |ij−ij+1|>1 for all 1≤j<k.
2. swap pij and pij+1 for all 1≤j≤k.
Now, for a given a string s=s1s2...sn, Professor Zhang wants to find all occurrences of all the generated patterns in s.
The first line contains two integers n and m (1≤n≤105,1≤m≤min{5000,n}) -- the length of s and p.
The second line contains the string s and the third line contains the string p. Both the strings consist of only lowercase English letters.
题意:给定一个长度为n的匹配串s和长度为m的模式串p,p可以进行变换,变换规则是任意交换两个相邻的字符,但是每个字符最多(被)交换一次。结果输出一个n位的二进制,对于匹配串的字符位置i,如果s的子串(si,si+1,si+2,...,si+m-1)可以由p串变换得出的话,则这个位置输出“1”,否则输出“0”
因为每个字符最多交换或者被交换一次,那么所有交换都是互不影响的,判断p是不是可以构造成目标串,只需O(m)地遍历一遍p串和对应位置的s串,遇到不可交换且不匹配就退出并输出0,否则全部匹配就输出1,然后O(n)地枚举s的所有子串,即可在O(nm)时间得出答案(显然i>n - m就直接输出0),严格上说这不算DP,但题解上说这是O(nm)的DP,所以也就是运用了一些dp的简单思想而已,代码如下:
#include <bits/stdc++.h>
using namespace std;
char s[100010];
char p[10010];
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
scanf("%s %s",s,p);
for(int i = 0 ; i < n ; i++)
{
if(i > n - m)
{
putchar('0');
continue;
}
bool f = true;
for(int j = 0 ; j < m ; j++)
{
if(j < m - 1 && p[j] == s[i + j + 1] && p[j + 1] == s[i + j])
j++;
else if(p[j] != s[i + j])
{
f = false;
break;
}
}
putchar(f ? '1' : '0');
}
puts("");
}
return 0;
}