poj 3167

Cow Patterns

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 3414   Accepted: 1263

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:

      1 4 4 3 2 1
In 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 9
then 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.

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.

Sample Input

9 6 10
5
6
2
10
10
7
3
2
9
1
4
4
3
2
1

Sample Output

1
3

Hint

Explanation of the sample:

The sample input corresponds to the example given in the problem statement.

There is only one match, at position 3 within FJ's sequence of N cows.

大意:

给出两个串 A,B 长度分别为 N,K, 两个串均由数字构成且大小不超过 S.

两个串能够匹配的定义是: 当且仅当匹配两个串的每个数字在匹配区间[L,R]内的排名相等,那么这两个串匹配.

求 B 在 A 中出现了多少次,并输出每次的匹配位置.

思路:

看上去像是 KMP 的问题吧. 但是匹配的定义有变化.....

我们现在就是要动态维护这个数字在这个匹配区间内的排名,就能够解决这个问题....

那么怎么维护呢? 题目中的 S 比较小, 所以暴力是没有问题的, 一个优化一点的方式是使用 BIT.

现在我们就要想办法确定这个区间的值了. 一个比较显然的结论(这为什么是充要条件我没想懂...)就是比x数字小,且和x数字相等的数相同就能够匹配.

一个预处理的过程就看程序吧.

然后在计算 kmp 的时候我们通过计算排名来确定匹配,然后通过 插入来维护排名....

一个需要注意的地方就是: 当 沿着 fail 指针回溯的时候, 我们要撤销操作..... 具体情况, 就看程序吧.

缩行党 && goto...... 自行无视

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn = (int)1.5e5;
 8 int n,k,s;
 9 int fail[maxn],str[maxn],pt[maxn];
10 pair<int,int>rk[maxn];
11 vector<int>v;
12 struct BIT{
13     int bit[50];
14     void clear(){memset(bit,0,sizeof(bit));}
15     inline int lowbit(int x){ return x & (-x); }
16     int less(int pos){ int ret = 0; for(;pos > 0; pos -= lowbit(pos)) ret += bit[pos]; return ret; }
17     void ins(int pos,int val){for(;pos <= 30; pos += lowbit(pos)) bit[pos] += val;}
18 }bit;
19 pair<int,int>rank(int x){
20     return make_pair(bit.less(x-1), bit.less(x));
21 }
22 void getfail(){
23     bit.clear();
24     fail[0] = -1;
25     for(int i = 1, j = 0; i < k;)
26         if(j == -1 || rank(pt[i]) == rk[j])
27             bit.ins(pt[i],1), i++, j++, fail[i] = j;
28         else{
29             for(int l = i - j; l < i - fail[j]; l++) bit.ins(pt[l],-1);
30             j = fail[j];
31         }       
32 }
33 void kmp(){
34     getfail();
35     bit.clear();
36     for(int i = 0,j = 0; i < n;){
37         if(j == -1 || rank(str[i]) == rk[j])
38             bit.ins(str[i],1), i++, j++;
39         else{
40         GT:     for(int l = i - j; l < i - fail[j]; l++) bit.ins(str[l],-1);
41             j = fail[j]; continue;
42         }
43         if(j == k) { v.push_back(i-j+1); goto GT;}
44     }        
45 }
46 int main()
47 {
48     freopen("mkp.in","r",stdin);
49     freopen("mkp.out","w",stdout);
50     scanf("%d %d %d
",&n,&k,&s);
51     for(int i = 0; i < n; ++i) scanf("%d",&str[i]);
52     for(int i = 0; i < k; ++i) scanf("%d",&pt[i]);
53     for(int i = 0; i < k; ++i) rk[i] = rank(pt[i]), bit.ins(pt[i],1);
54     kmp();
55     printf("%d
",v.size());
56     for(int i = 0; i < (int)v.size(); ++i) printf("%d
",v[i]);
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/Mr-ren/p/4223177.html