HDU5745解题报告 暴力压位

Problem Description
Professor Zhang would like to solve the multiple pattern matching problem, but he only has only one pattern string p=p1p2…pm. So, he wants to generate as many as possible pattern strings from p using the following method:

  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.

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

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.

Output
For each test case, output a binary string of length n. The i-th character is “1” if and only if the substring sisi+1…si+m−1 is one of the generated patterns.
网上搜了好多题解,全是sb的O(n*m)。。表示很无语。。赛上没敢写暴力。
这题其实是很好的一个学bitset暴力压位的题。。让我再次体会到二进制的魔法。。
这个题的转移方程很简单
dpi,j,ksitjt012
dpi,j,0=dpi1,j1,2 and si==tj1
dpi,j,1=(dpi1,j1,1 or dpi1,j1,0) and si==tj1
dpi,j,2=(dpi1,j1,1 or dpi1,j1,0) and si==tj+1
显然暴力会超时(没超时只是出题人挂数据的时候挂错了。。)
看下转移方程可以发现, ij 转移的时候是同步减少的。并且dp存的值是布尔型。
此类状态要自然而然的想到,把第一维或者第二维状压,以当前位1表示可以匹配,0表示不能匹配。然后转移的时候把之前的状态左移一位(增加一位,具体增加多少看转移状态而定)并且和预处理出来的26个字母匹配状态取and。
具体操作见代码

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxv = 5e3 + 10;
const double eps = 1e-9;

char s[maxn], t[maxv];
bitset  dp[2][3];
bitset  sta[26];
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int lens, lent;
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &lens, &lent);
        scanf("%s%s", s, t);
        for(int i = 0; i < 26; i++) {
            sta[i].reset();
        }
        for(int j = 0; j < lens; j++) {
            sta[s[j] - 'a'][j] = 1;
        }
        for(int i = 0; i < 2; i++) {
            for(int k = 0; k < 3; k++) {
                dp[i][k].reset();
            }
        }
        //1表示t[j]不交换,0表示t[j]与前面的交换,2表示t[j]与后面的交换
        dp[0][1] = sta[t[0]-'a'];
        if(lent > 1)
            dp[0][2] = sta[t[1]-'a'];
        int cur = 0;
        for(int i = 1; i < lent; i++) {
            cur ^= 1;
            dp[cur][1] = ((dp[cur^1][0] | dp[cur^1][1]) << 1) & sta[t[i]-'a'];
            dp[cur][0] = ((dp[cur^1][2]) << 1) & sta[t[i-1]-'a'];
            if(i < lent - 1)
                dp[cur][2] = ((dp[cur^1][0] | dp[cur^1][1]) << 1) & sta[t[i+1]-'a'];
        }
        for(int i = 0; i < lens; i++) {
            if(dp[cur][0][i+lent-1] || dp[cur][1][i+lent-1])
                printf("1");
            else printf("0");
        }
        puts("");
    }

    return 0;
}

你可能感兴趣的:(动态规划)