poj3167

来源:互联网 发布:厦门博思软件 编辑:程序博客网 时间:2024/06/06 00:44

这道题看别人代码看了一天,我去……功夫不行啊!

#include <iostream>#include <stdio.h>#include <vector>#include <string.h>using namespace std;const int maxn=25010;int n,m,s;vector<int> ans;int sum[maxn];int next[maxn];int tot1[maxn],tot2[maxn];int a[100010],b[maxn];int query(int x){    int tmp=0;    for(int i=1;i<=x;i++) tmp+=sum[i];    return tmp;}int main(){    scanf("%d%d%d",&n,&m,&s);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    for(int i=1;i<=m;i++)    {        scanf("%d",&b[i]);        tot1[i]=query(b[i]-1);        tot2[i]=query(b[i]);        sum[b[i]]++;    }    memset(sum,0,sizeof sum);    int j=0;    for(int i=2;i<=m;i++)    {        while(j&&(tot1[j+1]!=query(b[i]-1) || tot2[j+1]!=query(b[i])))//while:清除sum部分值,直到j=0(匹配到第一个了)或匹配        {            for(int k=i-j;k<i-next[j];k++)//(i-next[i]-(i-j))就是已经匹配的长度-1,-1是为了给下一段匹配留一个(形成匹配至少需要2个);i-j是这段匹配的开始                sum[b[k]]--;            j=next[j];        }        if(tot1[j+1]==query(b[i]-1) && tot2[j+1]==query(b[i])) j++;//如果匹配,j++        next[i]=j;//这个+1后的i=+1后的j,+1前的j或者是不+1的j是next[i-1]        sum[b[i]]++;//读取b[i]了,对应的sum+1    }    memset(sum,0,sizeof sum);    j=0;    for(int i=1;i<=n;i++)    {        while(j==m ||(j&& (tot1[j+1]!=query(a[i]-1) || tot2[j+1]!=query(a[i]))))//j==m说明成功匹配了一段,要清除sum部分值;直到匹配才结束while        {            for(int k=i-j;k<i-next[j];k++) sum[a[k]]--;            j=next[j];        }        if(tot1[j+1]==query(a[i]-1) && tot2[j+1]==query(a[i])) j++;        if(j==m) ans.push_back(i-m+1);        sum[a[i]]++;    }    printf("%d\n",ans.size());    int len=ans.size();    for(int i=0;i<len;i++) printf("%d\n",ans[i]);}
原创粉丝点击