Sereja ans Anagrams(map)

来源:互联网 发布:windows下修复grub 编辑:程序博客网 时间:2024/05/17 23:25
Sereja has two sequences a and b and number p. Sequence a consists of n integers a1, a2, ..., an. Similarly, sequence b consists of m integers b1, b2, ..., bm. As usual, Sereja studies the sequences he has. Today he wants to find the number of positions q (q + (m - 1)·p ≤ n; q ≥ 1), such that sequence b can be obtained from sequence aq, aq + p, aq + 2p, ..., aq + (m - 1)p by rearranging elements.Sereja needs to rush to the gym, so he asked to find all the described positions of q.

Input

The first line contains three integers n, m and p (1 ≤ n, m ≤ 2·105, 1 ≤ p ≤ 2·105). The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109). The next line contains m integers b1, b2, ..., bm (1 ≤ bi ≤ 109).

Output

In the first line print the number of valid qs. In the second line, print the valid values in the increasing order.

Example
Input

5 3 11 2 3 2 11 2 3Output21 3Input6 3 21 3 2 2 3 11 2 3Output21 2

还是模拟的思想,我们遍历所有能做起点的点,然后取数,当我们的数量等于目标序列的数量的时候,我们进行比较,可以的话,我们的总和就加1。
为了节省时间,我们都是一次+p+p+…直接到底,下次就不用再去把这些点当做起点了。

#include <cstdio>#include <cstring>#include<algorithm>#include <queue>#include <map>using namespace std;typedef long long ll;//不能只看n,m,p的范围,还要看他们的运算,题目中又有乘法,所以我们必须要llconst int Max=2e5+10;//这个题用map 的好处是什么,就是可以直接进行判断是不是想等,想一下,两个大数组直接一个等号,多么简单//只不过,map就算里面的值等于0了,他也不会自动删除,需要我们手动来完成int answer[Max];int a[Max];int vis[Max];map<int,int> mp;map<int,int> TM;int main(){    memset(vis,0,sizeof(vis));    ll n,m,p;    scanf("%I64d%I64d%I64d",&n,&m,&p);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    int x;    for(int i=1;i<=m;i++)        scanf("%d",&x),mp[x]++;//运算符重载[],可以直接当成数组用    int ans=0;    for(int i=1;i<=n&&i+(m-1)*p<=n;i++)    {        if(vis[i])//因为我们拿来一个点就直接m m m到底了,所以说一个数一旦被标记,他的所有可能性都尝试了            continue;        queue<int> q;//队列的目的,一个就是看数量,在一个就是先进先出的特点        TM.clear();        for(int j=i;j<=n;j+=p)        {            q.push(j);            vis[j]=1;            TM[a[j]]++;            if(q.size()==m)            {                if(TM==mp)                {                    answer[ans]=q.front();                    ans++;                }  //因为序列是连续的,所以我们可以去掉第一个点,看后面还能不能组成目标序列                int x=q.front();                q.pop();                TM[a[x]]--;//把临时地图中相应位置的数减一            //如果这点的数量已经为空了,但是这个节点还会有,我们需要清空它                if(!TM[a[x]])                    TM.erase(a[x]);//也是相当于下标            }        }    }    printf("%d\n",ans);    sort(answer,answer+ans);    for(int i=0;i<ans;i++)        printf("%d ",answer[i]);    return 0;}
原创粉丝点击