hdu 5745 dp+bitset

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

1. select some indices  i1,i2,...,ik i1,i2,...,ik such that  1i1<i2<...<ik<|p| 1≤i1<i2<...<ik<|p| and  |ijij+1|>1 |ij−ij+1|>1 for all  1j<k 1≤j<k
2. swap  pij pij and  pij+1 pij+1 for all  1jk 1≤j≤k

Now, for a given a string  s=s1s2...sn s=s1s2...sn, Professor Zhang wants to find all occurrences of all the generated patterns in  s s.
Input
There are multiple test cases. The first line of input contains an integer  T T, indicating the number of test cases. For each test case: 

The first line contains two integers  n n and  m m  (1n105,1mmin{5000,n}) (1≤n≤105,1≤m≤min{5000,n}) -- the length of  s s and  p p

The second line contains the string  s s and the third line contains the string  p p. Both the strings consist of only lowercase English letters.
Output
For each test case, output a binary string of length  n n. The  i i-th character is "1" if and only if the substring  sisi+1...si+m1 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

  1. 这道题定义f[i][j][k]表示—— 
  2. a串匹配到位点a[i] 
  3. b串匹配到位点b[j] 
  4. j这个位置的匹配状态为k(0表示b[j]要与b[j-1]交换,1表示没有交换,2表示b[j+1]交换) 
  5.  
  6. 转移方程是这个样子的—— 
  7. dp[i][j][0]=dp[i-1][j-1][2] & (a[i]==b[j-1]) 
  8. //a[i-1]与b[0~j-1]匹配了,且a[i]实际要与b[j-1]做匹配 
  9.  
  10. dp[i][j][1]=dp[i-1][j-1][0] & (a[i]==b[j]) 
  11. |dp[i-1][j-1][1] & (a[i]==b[j]) 
  12. //a[i-1]与b[0~j-1]匹配了,且a[i]实际要与b[j]做匹配 
  13.  
  14. dp[i][j][2]=dp[i-1][j-1][0] & (a[i]==b[j+1]) 
  15. |dp[i-1][j-1][1] & (a[i]==b[j+1]) 
  16. //a[i-1]与b[0~j-1]匹配了,且a[i]实际要与b[j+1]做匹配

ac代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m;
char a[N],b[5007],ans[N];
bitset<N>dp[3],num[26];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%s%s",&n,&m,a+1,b+1);
        for(int i=0;i<=25;i++)
        num[i].reset();
        for(int i=1;i<=n;i++)
        num[a[i]-'a'][i]=1;
        for(int i=0;i<=2;i++)
        dp[i].reset();
        dp[0].set();
        for(int i=1;i<=m;i++)
        {
           int x=b[i]-'a',y=b[i-1]-'a',z=b[i+1]-'a';
           dp[0]=((dp[0]|dp[1])<<1);
           if(i>1)
           dp[1]=(dp[2]<<1)&num[y];
           if(i<m)
           dp[2]=dp[0]&num[z];
           dp[0]&=num[x];
        }
        for(int i=m;i<=n;i++)
        ans[i-m+1]='0'+(dp[0][i]|dp[1][i]);
        for(int i=n-m+2;i<=n;i++)
        ans[i]='0';
        ans[n+1]=0;
        puts(ans+1);
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值