poj 3167 Cow Patterns(kmp)
来源:互联网 发布:java 时间控件 编辑:程序博客网 时间:2024/05/20 06:05
Cow Patterns
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 3127 Accepted: 1153
Description
A particular subgroup of K (1 <= K <= 25,000) of Farmer John's cows likes to make trouble. When placed in a line, these troublemakers stand together in a particular order. In order to locate these troublemakers, FJ has lined up his N (1 <= N <= 100,000) cows. The cows will file past FJ into the barn, staying in order. FJ needs your help to locate suspicious blocks of K cows within this line that might potentially be the troublemaking cows.
FJ distinguishes his cows by the number of spots 1..S on each cow's coat (1 <= S <= 25). While not a perfect method, it serves his purposes. FJ does not remember the exact number of spots on each cow in the subgroup of troublemakers. He can, however, remember which cows in the group have the same number of spots, and which of any pair of cows has more spots (if the spot counts differ). He describes such a pattern with a sequence of K ranks in the range 1..S. For example, consider this sequence:
If the true count of spots for some sequence of cows is:
Please help FJ locate all the length-K subsequences in his line of cows that match his specified pattern.
FJ distinguishes his cows by the number of spots 1..S on each cow's coat (1 <= S <= 25). While not a perfect method, it serves his purposes. FJ does not remember the exact number of spots on each cow in the subgroup of troublemakers. He can, however, remember which cows in the group have the same number of spots, and which of any pair of cows has more spots (if the spot counts differ). He describes such a pattern with a sequence of K ranks in the range 1..S. For example, consider this sequence:
1 4 4 3 2 1In this example, FJ is seeking a consecutive sequence of 6 cows from among his N cows in a line. Cows #1 and #6 in this sequence have the same number of spots (although this number is not necessarily 1) and they have the smallest number of spots of cows #1..#6 (since they are labeled as '1'). Cow #5 has the second-smallest number of spots, different from all the other cows #1..#6. Cows #2 and #3 have the same number of spots, and this number is the largest of all cows #1..#6.
If the true count of spots for some sequence of cows is:
5 6 2 10 10 7 3 2 9then only the subsequence 2 10 10 7 3 2 matches FJ's pattern above.
Please help FJ locate all the length-K subsequences in his line of cows that match his specified pattern.
Input
Line 1: Three space-separated integers: N, K, and S
Lines 2..N+1: Line i+1 describes the number of spots on cow i.
Lines N+2..N+K+1: Line i+N+1 describes pattern-rank slot i.
Lines 2..N+1: Line i+1 describes the number of spots on cow i.
Lines N+2..N+K+1: Line i+N+1 describes pattern-rank slot i.
Output
Line 1: The number of indices, B, at which the pattern matches
Lines 2..B+1: An index (in the range 1..N) of the starting location where the pattern matches.
Lines 2..B+1: An index (in the range 1..N) of the starting location where the pattern matches.
Sample Input
9 6 1056210107329144321
Sample Output
13
题意:告诉你n个数组成的串,和一个等级序列,问你符合这个等级序列的子串个数,和这些子串的起始位置。
思路:
如果不是符合等级,而是完全符合的话,直接用kmp就可以搞定。但是,这题的话,next数组怎么求呢?
我们知道,在求next数组的时候是用递推的:
if(p[i] == p[next[i]]) next[i+1] = next[i]+1;
本题在什么情况下p[i] == p[next[i]]? 当且仅当p[i]在p[k](i-next[i]<=k<=i-1)间的等级 ==p[next[i]]在p[k](0<=k<=next[i]-1)间的等级时才相等。即如图:开二维数组sum[i][25]来预处理记录从第0~i位,25内个数字出现的次数,就可以推出某个区间比p[k]小的数有多少个了!(当然,和p[k]相等的个数也可以求出来,就是比p[k]+1小的减去比p[k]小的)!
#include <iostream>#include <cstdio>#include <map>#include <vector>using namespace std;const int maxn1 = 100100;const int maxn2 = 25010;const int maxn3 = 27;int Rank[maxn2] , spot[maxn1];map<int , int> mp;int N , K , S , Next[maxn2];int sumS[maxn1][maxn3] , sumR[maxn2][maxn3] , cnt;vector<int> ans;void initial(){ for(int i = 0; i < maxn1; i++) spot[i] = 0; for(int i = 0; i < maxn2; i++) Rank[i] = 0 , Next[i] = 0; //for(int i = 0; i < maxn3; i++){ //for(int j = 0; j < maxn1; j++) sumS[j][i] = 0; //for(int j = 0; j < maxn2; j++) sumR[j][i] = 0; // }//初始化这里用G++交超时,C++1907MS。去掉G++907MS。- -!... mp.clear(); ans.clear(); cnt = 1;}void readcase(){ for(int i = 0; i < N; i++){ scanf("%d" , &spot[i]); } for(int i =0; i < K; i++){ scanf("%d" , &Rank[i]); mp[Rank[i]] = 0; } for(map<int,int>::iterator it = mp.begin(); it != mp.end(); it++) it->second = cnt++; for(int i = 0; i < K; i++){ Rank[i] = mp[Rank[i]]; }}void get_sum(){ sumS[1][spot[0]] = 1; sumR[1][Rank[0]] = 1; for(int i = 1; i < N; i++){ for(int j = 0; j < maxn3; j++) sumS[i+1][j] = sumS[i][j]; sumS[i+1][spot[i]]++; } for(int i = 1; i < K; i++){ for(int j = 0; j < maxn3; j++) sumR[i+1][j] = sumR[i][j]; sumR[i+1][Rank[i]]++; }}int getSpot_status(int l , int r , int num){ int sta = 0; for(int i = 0; i < num; i++){ if(sumS[r][i]-sumS[l][i]>0) sta++; } return sta;}int getRank_status(int l , int r , int num){ int sta = 0; for(int i = 0; i < num; i++){ if(sumR[r][i]-sumR[l][i] > 0) sta++; } return sta;}void getNext(){ Next[0] = -1; for(int i = 0; i < K; i++){ int next = Next[i]; while(next >= 0 && !(getRank_status(0 , next , Rank[next]) == getRank_status(i-next , i , Rank[i]) && getRank_status(0 , next , Rank[next]+1) == getRank_status(i-next , i , Rank[i]+1))){ next = Next[next]; } Next[i+1] = next+1; }}void kmp(){ getNext(); /*for(int i = 0; i < K; i++){ cout << Next[i] << " "; } cout << endl;*/ int r = 0 , s = 0; while(s < N){ if(getRank_status(0 , r , Rank[r]) == getSpot_status(s-r , s , spot[s])&&getRank_status(0 , r , Rank[r]+1) == getSpot_status(s-r , s , spot[s]+1)){ s++; r++; }else{ r = Next[r]; if(r < 0){ s++; r = 0; } } if(r >= K){ r = Next[r]; ans.push_back(s-K+1); } }}void computing(){ get_sum(); kmp(); printf("%d\n" , ans.size()); for(int i = 0; i < ans.size(); i++) printf("%d\n" , ans[i]);}int main(){ while(scanf("%d%d%d" , &N , &K , &S) != EOF){ initial(); readcase(); computing(); } return 0;}
0 0
- poj 3167 Cow Patterns(kmp)
- POJ-3167- Cow Patterns(KMP)
- poj 3167 Cow Patterns kmp
- [POJ] 3167 Cow Patterns (KMP+树状数组)
- POJ 3167 Cow Patterns (KMP + 树状数组)
- POJ 3167 Cow Patterns KMP+暴力
- pku 3167 Cow Patterns(kmp)
- poj 3167 Cow Patterns ... 四种算法 (均结合kmp)
- poj 3167 Cow Patterns (kmp + 线段树/树状数组)
- POJ 3167 Cow Patterns
- POJ 3167 Cow Patterns
- POJ 3167 Cow Patterns
- POJ 3167 Cow Patterns
- POJ 3167 Cow Patterns
- POJ3167 Cow Patterns (KMP)
- [kmp] POJ3167 Cow Patterns
- Poj 3167 Cow Patterns Hdu 4749 Parade Show (KMP大小关系相同匹配+树状数组)
- Cow Patterns poj 3167 (hash解法)
- MFC hook注入dll,远程线程注入dll
- 一种经典的网络游戏服务器架构
- WPF Control event 触发
- xml基础训练
- 歧路亡羊
- poj 3167 Cow Patterns(kmp)
- ecshop属性筛选时,同一属性名下,不同属性值的排序问题
- Java 利用SWFUpload多文件上传 session 为空失效,不能验证的问题
- 15.1-工资数据的输入
- windows下搭建Qt的Android开发环境
- perlin 噪声
- JAVA版4096
- 15.1-2(工资数据的输入)
- MySQL学习笔记之五 有关数据表操作