HDU 5745 La Vie en rose(bitset+dp)

题目: 传送门  
题意:给你一个p模式串,根据1、2两条规则变形,然后在s串中找符合p模式串的位置。 
题解:bitset就相当于一个bool类型的数组,但是它可以方便的进行位运算,比如int类型最多进行32位的位运算,bitset可以进行任意位的位运算,具体资料以及各种操作的复杂度可以百度。然后讲讲dp部分,dp[now][i]存的是now位置i状态下满足条件的位置。另外开一个bitset数组a[26]用来记录每种字母在s串中出现的位置。从上一个位置转移到下一个位置如下图: 
这里写图片描述  
一共三种状态:0–与前面位置交换;1–不交换;2–与后面位置交换(根据题意p串只能前后交换且同一个字符不会交换多次)。状态转移如下图: 

这里写图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PDD pair<double,double>
#define PLL pair<LL,LL>
#define MP(a,b) make_pair(a,b)
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define MAXLL 0x3f3f3f3f3f3f3f3f
#define N 100005
#define EPS 1e-12
#define PI acos(-1.0)
#define MAX_SIZE 1100005
#define pb push_back
#define IN freopen("squary.in","r",stdin)
#define OUT freopen("squary.out","w",stdout)
#define fi first
#define se second

bitset<N> dp[2][3], a[26];
int n, m;
char s[N], p[5005];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        scanf("%s%s", s, p);
        for(int i = 0; i < 26; i++)
            a[i].reset();
        for(int i = 0; i < n; i++)
            a[s[i] - 'a'][i] = 1;
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 3; j++)
                dp[i][j].reset();
        dp[0][1] = a[p[0] - 'a'];
        if(m > 1)
            dp[0][2] = a[p[1] - 'a'];
        int now = 0, pre = 1;
        for(int i = 1; i < m; i++)
        {
            pre = now;
            now ^= 1;
            dp[now][0] = dp[pre][2] & (a[p[i - 1] - 'a'] >> i);
            dp[now][1] = (dp[pre][1] | dp[pre][0]) & (a[p[i] - 'a'] >> i);
            if(i + 1 < m)
                dp[now][2] = (dp[pre][1] | dp[pre][0]) & (a[p[i + 1] - 'a'] >> i);
        }
        for(int i = 0; i < n; i++)
        {
            if(dp[now][0][i] || dp[now][1][i])
                printf("1");
            else
                printf("0");
        }
        puts("");
    }
}

猜你喜欢

转载自blog.csdn.net/cyf199775/article/details/80983355
en
LA