hdu 5745La Vie en rose(dp+bitset优化)

题目链接

La Vie en rose

Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3188 Accepted Submission(s): 888

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.

Sample Input
3
4 1
abac
a
4 2
aaaa
aa
9 3
abcbacacb
abc

Sample Output
1010
1110
100100100

Author
zimpha

Source
2016 Multi-University Training Contest 2

题意:

给出长度为 \(n\) 的字符串 \(s\) 和长度为 \(m\) 的字符串 \(t\) ,可以任意交换字符串 \(t\) 的相邻位置(同一个位置不能多次交换,也可以不交换)产生生成串,问 \(s\) 的每个位置 \(i\) 开始的字符串\(s_i,s_{i+1},…,s_{i+m-1}\) 是否是一个 \(t\) 的生成串,是输出1,否则0.

题解:

\(d[i][j][0]\) 表示 \(s\)\(i\) 位置和 \(t\) 能否匹配 \(j\) 的长度,且 \(j\) 位置不能与后面交换(但可能跟前面交换,看作一种情况),\(d[i][j][1]\) 表示 \(s\)\(i\) 位置和 \(t\) 能否匹配 \(j\) 的长度,且 \(j\) 位置与后面交换
转移方程为:

\(d[i][j][0]=((d[i-1][j-1][1]\) & $ s[i]==t[j-1])|(d[i-1][j-1][0]$ & \(s[i]==t[j]))\)

\(d[i][j][1]=d[i-1][j-1][0]\) & \(s[i]==t[j+1]\).

这样做是 \(O(n*m)\) 的,复杂度较高,我们可以用 \(i\) 这一维用 \(bitset\) 记录,观察到 \(j\) 这一维只与前一项有关,滚动数组即可,关于 \(s[i]==t[j+1]\) 这样的等式可以预处理串 \(s\) 的每个字母出现的位置,就可以快速位运算了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=1e5+10;
bitset<maxn> d[2][2],p[27],ans;
char s[maxn],s1[maxn];
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s%s",s+1,s1+1);
        rep(i,0,26) p[i].reset();
        rep(i,1,n+1) p[s[i]-'a'].set(i);
        int cur=0;
        d[cur][0].reset(),d[cur][1].reset();
        d[cur][0]=p[s1[1]-'a'];
        if(m>1)
        d[cur][1]=p[s1[2]-'a'];
        rep(i,2,m+1)
        {
            cur^=1;
            d[cur][0]=(d[cur^1][1]<<1)&p[s1[i-1]-'a'];
            d[cur][0]|=(d[cur^1][0]<<1)&p[s1[i]-'a'];
            if(i<m)
            d[cur][1]=(d[cur^1][0]<<1)&p[s1[i+1]-'a'];
        }
        ans=d[cur][0];
        rep(i,1,n+1)
        {
            if(i+m-1<=n)
            {
                if(ans[i+m-1]) printf("1");
                else printf("0");
            }
            else printf("0");
        }
        puts("");
    }
    return 0;
}
posted @ 2017-09-03 21:43  tarjan's  阅读(109)  评论(0编辑  收藏  举报