poj 2541 (kmp 或 状压dp)
2013-10-12 00:28
218 查看
题目:http://poj.org/problem?id=2541
题目大意:给你一个长度为n的01组成的字符串,0表示下雨,1表示晴,现在要预测n+1天的天气,找到一个长度最大且最靠后的一个
位置,它的前缀等于整个字符串的后缀,且长度要 <= 13,如果没有符合的,那么这一天就是0,再接着预测下一天,现在让你输出后面
l天的天气。
思路:倒着进行KMP,如果纯粹是这样,肯定爆掉,这里还有一个剪枝,那就是如果当前max_len == 13 了,那么就没必要再往后求
fail 了,就直接break掉。倒是我感觉如果是最差的极端数据,也可能会爆掉,poj嘛,可能是数据比较水吧。。
其实我自己先开始的想法是找循环,就没有考虑时间问题,因为很快就能进入循环,WA了几遍,后来发现找循环本身就是错的,题目没有理解
的问题吧。。。 = =
另外一种解法是状态压缩DP(佩服,反正我是没想到。。),设d[ i ][ j ]表示长度为 i 值为 j 的字符串的最右出现的最后一个字符的
位置(因为对于同一个值,有可能出现不同的字符串,0的存在,所以二维),那么就只需要一遍更新过去就行了,先判断,再更新。
复杂度为O(13 * (n + l))。我感觉这个才是正解。。。
DP版代码如下:
KMP版代码如下:
题目大意:给你一个长度为n的01组成的字符串,0表示下雨,1表示晴,现在要预测n+1天的天气,找到一个长度最大且最靠后的一个
位置,它的前缀等于整个字符串的后缀,且长度要 <= 13,如果没有符合的,那么这一天就是0,再接着预测下一天,现在让你输出后面
l天的天气。
思路:倒着进行KMP,如果纯粹是这样,肯定爆掉,这里还有一个剪枝,那就是如果当前max_len == 13 了,那么就没必要再往后求
fail 了,就直接break掉。倒是我感觉如果是最差的极端数据,也可能会爆掉,poj嘛,可能是数据比较水吧。。
其实我自己先开始的想法是找循环,就没有考虑时间问题,因为很快就能进入循环,WA了几遍,后来发现找循环本身就是错的,题目没有理解
的问题吧。。。 = =
另外一种解法是状态压缩DP(佩服,反正我是没想到。。),设d[ i ][ j ]表示长度为 i 值为 j 的字符串的最右出现的最后一个字符的
位置(因为对于同一个值,有可能出现不同的字符串,0的存在,所以二维),那么就只需要一遍更新过去就行了,先判断,再更新。
复杂度为O(13 * (n + l))。我感觉这个才是正解。。。
DP版代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 1111111; int d[14][1<<14]; char str[MAXN]; int main() { int n,l; while(~scanf("%d%d",&n,&l)) { scanf("%s",str+1); memset(d,-1,sizeof(d)); for(int i = 1;i<=n+l;i++) { if(i >= n) { int pos = -1; int tmp = 0; for(int j = 1;j<=13;j++) { if(i - j + 1 <= 0) break; tmp = (tmp<<1) + str[i - j + 1] - '0'; if(d[j][tmp] != -1) { pos = d[j][tmp]; } } if(pos != -1) { str[i+1] = str[pos+1]; } else str[i+1] = '0'; //printf("i = %d,pos = %d\n",i,pos); } int tmp = 0; for(int j = 1;j<=13;j++) { if(i - j + 1 <= 0) break; tmp = (tmp << 1) + str[i - j + 1] - '0'; d[j][tmp] = i; } } for(int i = 1;i<=l;i++) printf("%c",str[n+i]); puts(""); } return 0; } /* 10 7 1101110010 5 5 00001 */
KMP版代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 1111111; int n; char str[MAXN]; int fail[MAXN]; void get_fail() { int max_len = 0; int pos; fail[n-1] = n; int j = n; for(int i = n-2 ;i>=0;i--) { while(j < n && str[i] != str[j-1]) j = fail[j]; if(str[i] == str[j-1]) j--; fail[i] = j; int len = n - 1 - fail[i] + 1; if(len <= 13 && len > max_len) { max_len = len; pos = i; if(max_len == 13) break; } } //printf("max_len = %d,pos = %d\n",max_len,pos); if(max_len) str = str[pos + max_len]; else str = '0'; } int main() { int l; while(~scanf("%d%d",&n,&l)) { scanf("%s",str); for(int i = 0;i<l;i++,n++) { get_fail(); } for(int i = 0;i<l;i++) printf("%c",str[n-l+i]); puts(""); } return 0; }
相关文章推荐
- poj 2541 Binary Witch(状压dp)
- POJ 2541 Binary Witch 状压DP
- poj 3254 Corn Fields 状压dp入门
- POJ 2411 Mondriaan's Dream (状压dp)
- poj 2686 Traveling by Stagecoach(状压dp)
- poj 3420 Quad Tiling 状压dp
- POJ 3311 Hie with the Pie (状压DP)
- [poj 1699]Best Sequence[kmp][DP]
- POJ 3254 Corn Fields(状压DP入门)
- poj 2441 Arrange the Bulls(状压DP入门)
- POJ--2923--Relocation--状压DP
- POJ 3254 Corn Fields (状压DP)
- POJ 2923 状压DP
- poj 2288 Islands and Bridges(状压dp)
- NOI 2001 & poj 1185 && NYOJ 85 炮兵阵地(状压dp)
- POJ 1185 炮兵阵地(状压dp)
- 炮兵阵地 - POJ 1185 状压dp
- poj 1185(状压dp)
- POJ 3254-状压dp
- poj 1699 TSP(状态压缩DP) + KMP