HDU5745解题报告 暴力压位

本文介绍了一种使用bitset优化的模式匹配算法,通过巧妙的状态压缩和转移方程实现高效匹配,适用于字符串搜索问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <bitset>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#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 <maxn> dp[2][3];
bitset <maxn> 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;
}

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值