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