题目链接:http://acm.hdu.edu.cn/submit.php?pid=5745
转载声明:http://blog.csdn.net/u012015746/article/details/51992281 (题解)
转载声明:http://blog.csdn.net/qll125596718/article/details/6901935 (bitset介绍)
题意:
个人感想:
我这种弱渣完全不会这种dp题,我怎么想我也觉得是kmp什么的匹配.那时比赛想到头都疼,本来想写个暴力试试能不能过,却被队友草了一脸…但是结果出来原来暴力都可以过.实在无语,非不让我尝试一下.好吧,回到正题.
首先呢这道题呢我也是借鉴上面的博客,还有问了一下大牛怎么回事我才懂了.我本来看了下题解,我觉得很容易啊,我写了个很朴素的DP,绝壁超时(可以滚到最后面看看咯…不过没啥用).因为都跑了15E次… 然后看了一下题解。。
Bitset!!(上面的链接可以了解下),这东西我也没说过,很神奇.不过大牛说暴力还比标程快…尼玛
好吧说说我的理解(大牛教我的…)吧.
假设样例
abcbacacb
abc
首先 把原串(org)每种字符的位置存下来(bitset存的二进制是从右到左存的!!请注意)
a:001010001;
b:100001010;
c:010100100;
为什么这样做呢?因为当pat匹配位置的时候,这是pat 当前i 对应字串能匹配的位置(不管pat后面的),这时我们就需要用他来承接上一次dp的结果并且相&,
假设我上一次的结果是 001010001;那么下一位b假设是在后面就是 01010010,相&(按道理)应该是01010010的答案才是对的啊…可是这两个相与就等于0!了,明显错的!所以每次得到的dp就必须往左移一位这样才能表示一种承接关系,因为既然pat串的 i-1位置适配了,那么下一个位置也要适配,往左相&一下才行,其他的还是按照dp的思想.
我是第一次做这种题目,所以也理解不够深,这是我遇到的情况了.
分析:DP+bitset.
AC代码:
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
#include <bitset>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
const int maxm=5e3+10;
int N,M;
int T;
char org[maxn];
char pat[maxm];
bitset<maxn> w[26];
bitset<maxn> dp[2][3];
int ans[maxn];
int main()
{
#ifdef OUT
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
scanf("%s",org+1);
scanf("%s",pat+1);
for(int i=0;i<26;i++)w[i].reset();
for(int i=1;i<=N;i++)
{
w[org[i]-'a'][i-1]=1;
}
dp[0][0].set();//没交换
dp[0][1].reset();//和前面交换
dp[0][2].reset();//和后面交换
for(int i=1;i<=M;i++)
{
int cur=i&1;
int last=(i-1)&1;
int now=pat[i]-'a';
int pre=pat[i-1]-'a';
int sur=pat[i+1]-'a';
dp[cur][0].reset();
dp[cur][1].reset();
dp[cur][2].reset();
dp[cur][0]=((dp[last][1] | dp[last][0])&w[now])<<1;
if(i>1) dp[cur][1]=((dp[last][2])&w[pre])<<1;
if(i<M) dp[cur][2]=((dp[last][0] | dp[last][1])&w[sur])<<1;
}
memset(ans,0,sizeof(ans));
for(int j=1;j<=N;j++)
{
if(dp[M&1][0][j] | dp[M&1][1][j]) ans[j-M+1]=1;
}
for(int i=1;i<=N;i++)
{
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}
个人代码:
/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/
//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int T;
int N,M;
char org[maxn];
char pat[maxn];
bool dp[maxn][3][3];
void init()
{
memset(dp,false,sizeof(dp));
}
int main()
{
#ifdef OUT
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d",&N,&M);
scanf("%s",org);
scanf("%s",pat);
for(int j=0;j<M;j++)
{
for(int i=0;i<N;i++)
{
int J=j%3;
int lJ=J-1;
if(lJ<0)lJ+=3;
if(j==0)
{
dp[i][j][1]=(org[i]==pat[j]);
dp[i][j][2]=(org[i]==pat[j+1]);
}
else
{
if(i==0)continue;
dp[i][J][0]=dp[i-1][lJ][2]&&(org[i]==pat[j-1]);
dp[i][J][1]=(dp[i-1][lJ][1]||dp[i-1][lJ][0])&&(org[i]==pat[j]);
dp[i][J][2]=(dp[i-1][lJ][1]||dp[i-1][lJ][0])&&(org[i]==pat[j+1]);
}
}
}
int J=(M-1)%3;
for(int i=M-1;i<N;i++)
{
if(dp[i][J][0]||dp[i][J][1])printf("1");
else printf("0");
}
for(int j=0;j<M-1;j++)
{
printf("0");
}
cout<<endl;
}
return 0;
}