poj3167 Cow Patterns

原创 2016年08月28日 15:29:43

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.

对于两个子串,如果对于每个位置,都有【在他之前且小于他】的元素的个数相等,且【在他之前且小于等于他】的元素个数相等,那么这两个子串就是等价的。
而且注意到,如果两个子串相等,那么在他们后面再添加一个元素的时候,只需要验证新添加的元素是否符合即可,前面的元素不受影响。
于是可以借用字符串中的kmp算法进行模式匹配。
对应的,判断条件b[j+1]==a[i]就变成了
tot1[j+1]==qry(a[i]-1)&&tot2[j+1]==qry(a[i])
其中tot1(2)[k]表示串b[1..k]中小于(小于等于)b[k]的个数,可以预处理出来,qry(x)表示询问小于等于x的数的个数。
在进行i++,j++,j=next[j]的同时也要注意维护当前串中数的个数。
考虑到s<=15,直接开数组维护即可,如果s较大,可以用树状数组优化到单步操作O(logs)。

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
vector<int> ans;
int a[100010],b[25010],next[25010],sum[30],cnt[30],s,tot1[25010],tot2[25010];
int qry(int x)
{
    int ans=0;
    for (int i=1;i<=x;i++)
      ans+=sum[i];
    return ans;
}
int main()
{
    int i,j,k,m,n,p,q,x,y,z;
    scanf("%d%d%d",&n,&m,&s);
    for (i=1;i<=n;i++)
      scanf("%d",&a[i]);
    for (i=1;i<=m;i++)
      scanf("%d",&b[i]);
    for (i=1;i<=m;i++)
    {
        tot1[i]=qry(b[i]-1);
        tot2[i]=qry(b[i]);
        sum[b[i]]++;
    }
    memset(sum,0,sizeof(sum));
    for (i=2,j=0;i<=m;i++)
    {
        while (j&&(tot1[j+1]!=qry(b[i]-1)||tot2[j+1]!=qry(b[i])))
        {
            for (k=i-j;k<i-next[j];k++)
              sum[b[k]]--;
            j=next[j];
        }
        if (tot1[j+1]==qry(b[i]-1)&&tot2[j+1]==qry(b[i])) j++;
        next[i]=j;
        sum[b[i]]++;
    }
    memset(sum,0,sizeof(sum));
    for (i=1,j=0;i<=n;i++)
    {
        while (j==m||(j&&(tot1[j+1]!=qry(a[i]-1)||tot2[j+1]!=qry(a[i]))))
        {
            for (k=i-j;k<i-next[j];k++)
              sum[a[k]]--;
            j=next[j];
        }
        if (tot1[j+1]==qry(a[i]-1)&&tot2[j+1]==qry(a[i])) j++;
        if (j==m) ans.push_back(i-m+1);
        sum[a[i]]++;
    }
    printf("%d\n",ans.size());
    for (i=0;i<ans.size();i++)
      printf("%d\n",ans[i]);
}
版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。

相关文章推荐

【KMP】【poj3167】【bzoj1729】Cow Patterns

题意 给定一个顺序序列表示奶牛的排列顺序,定义串a=b当且仅当a的每位的排名=b的每位的排名。 题解 预处理出前i位中j出现的次数,由于编号很小,处理出类似前缀和,暴力查询排名即可。已知排名之后就...

poj3167

同hdu 4749import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOExcepti...

POJ 3167 Cow Patterns (KMP + 树状数组)

题意:在长度为n的主串中,用长度为k的模式串匹配,找出所有匹配的起始位置。匹配机制不是相等,而是找出的子串满足与模式串相同的大小关系。 例如样例:N:5 6 2 10 10 7 3 2 9    K...

kmp poj 3167

参考了这个http://www.cppblog.com/zxb/archive/2010/10/06/128782.aspx?opt=admin 他用的是hash的思想 题目大意是:给一个字符串,...

POJ 3167 Cow Patterns

题意:给定长度为n和m的两个数字序列(数均小于等于25),用m去按照一定方式去匹配n,即:如果n中的区间[a,b]各数字的名次与m中各数字的名次完全一样,那么他们就是匹配的。问题:求所有的匹配个数及他...

POJ 3167 Cow Patterns

题目链接:http://poj.org/problem?id=3167Description约翰的N(1≤N≤100000)只奶牛中出现了K(1≤K≤25000)只爱惹麻烦的坏蛋。奶牛们按一定的顺序排...

POJ-3167- Cow Patterns(KMP)

Cow Patterns Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4184   A...

poj 3167 Cow Patterns ... 四种算法 (均结合kmp)

题目链接:http://poj.org/problem?id=3167 第1,2种算法思路是一样的,但是实现方法不同。 算法归于以下结论:两个序列的偏序相同则两序列同一位以前小于它和等于它...

poj 3167 Cow Patterns (kmp + 线段树/树状数组)

这道题确实让我更加深入的了解了kmp。。。。 以前的匹配只要字符或者是数值一样就可以,这道题是区间名次一样进行匹配的。 一个数在区间中的名次可以转化为,它前面比他小的数的个数,和他相等的个数,和比...

POJ 3167 Cow Patterns

kmp + 树状数组。树状数组动态更新排名。明白了方法以后,细节方面调了半天。。。想吐了。。。逗b的地方也不想改了。注意代码中注释的地方。 真的要想清楚再写,不然很浪费时间。 #include #i...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj3167 Cow Patterns
举报原因:
原因补充:

(最多只允许输入30个字)