『HDU 5745』La Vie en rose
題目鏈接: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 OUTfreopen("coco.txt","r",stdin);freopen("lala.txt","w",stdout); #endifscanf("%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 OUTfreopen("coco.txt","r",stdin);freopen("lala.txt","w",stdout); #endifscanf("%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; }總結
以上是生活随笔為你收集整理的『HDU 5745』La Vie en rose的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32系列单片机编程中的IS_GPI
- 下一篇: C51单片机计数器实验