POJ 3167 Cow Patterns (KMP + 树状数组)
2013-10-02 20:41
330 查看
题意:在长度为n的主串中,用长度为k的模式串匹配,找出所有匹配的起始位置。匹配机制不是相等,而是找出的子串满足与模式串相同的大小关系。
例如样例:N:5 6 2 10 10 7 3 2 9 K:1 4 4 3 2 1。找出的子串为: 2 10 10 7 3 2,满足模式串中的任意i , j的大小关系。
现在需要一种判别方式代替普通的相等判别,就能变成kmp做法了。
用lee[i] 保存在 i 结点之前(包括i结点),小于等于val [i] 的个数
les [i] 保存在 i 结点之前(包括i结点),小于val [i] 的个数
得出的结论是:如果lee[i] == lee[j] && les[i] == les[j] 成立,则说明第i个位置和第j 个位置匹配,否则跳转next [j]
例如样例:N:5 6 2 10 10 7 3 2 9 K:1 4 4 3 2 1。找出的子串为: 2 10 10 7 3 2,满足模式串中的任意i , j的大小关系。
现在需要一种判别方式代替普通的相等判别,就能变成kmp做法了。
用lee[i] 保存在 i 结点之前(包括i结点),小于等于val [i] 的个数
les [i] 保存在 i 结点之前(包括i结点),小于val [i] 的个数
得出的结论是:如果lee[i] == lee[j] && les[i] == les[j] 成立,则说明第i个位置和第j 个位置匹配,否则跳转next [j]
#include <iostream> #include <algorithm> #include <cmath> #include<functional> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <vector> #include <set> #include <queue> #include <stack> #include <climits>//形如INT_MAX一类的 #define MAX 100005 #define INF 0x7FFFFFFF using namespace std; int n,k,s; int c[33],a[MAX],b[31111]; int next[MAX]; int lee[MAX],les[MAX]; int ans , pos[MAX]; void init() { ans = 0; memset(c,0,sizeof(c)); memset(lee,0,sizeof(lee)); memset(les,0,sizeof(les)); memset(next,0,sizeof(next)); } int lowbit(int x) { return x & (-x); } void update(int x,int va) { while(x <= s) { c[x] += va; x += lowbit(x); } } int query(int x) { int sum = 0; while(x > 0) { sum += c[x]; x -= lowbit(x); } return sum; } void getnext() { memset(c,0,sizeof(c)); int i = 1, j = 0; while(i <= k) { if(j == 0 || (query(b[i] - 1) == les[j] && query(b[i]) == lee[j])) { //匹配条件 i ++; j ++; next[i] = j; if(i <= k) update(b[i],1); //满足匹配后加入 } else { for(int l=i-j+1; l<=i-next[j]; l++) update(b[l],-1); //不满足匹配,删去这一轮加入的 j = next[j]; } } } void newkmp() { memset(c,0,sizeof(c)); int i = 1, j = 1; update(a[1],1); while(i <= n) { if(j == 0 || (query(a[i] - 1) == les[j] && query(a[i]) == lee[j])) { i ++; j ++; if(i <= n) update(a[i],1); } else { for(int l=i-j+1; l<=i-next[j]; l++) update(a[l],-1); j = next[j]; } if(j > k) { //要找出所有的起始位置,所以next[k] == 1; for(int l=i-j+1; l<=i-next[j]; l++) update(a[l],-1); j = next[j]; pos[ans++] = i - k; } } } //void test() { // for(int i=1; i<=k; i++) printf("next : %d %d\n",i,next[i]); //} int main() { while(scanf("%d%d%d",&n,&k,&s) != EOF) { init(); for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=k; i++) scanf("%d",&b[i]); for(int i=1; i<=k; i++) { update(b[i],1); lee[i] = query(b[i]); les[i] = query(b[i] - 1); } getnext(); //test(); newkmp(); printf("%d\n",ans); for(int i=0; i<ans; i++) printf("%d\n",pos[i]); } return 0; }
相关文章推荐
- 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 (KMP+前缀和)
- Poj 3167 Cow Patterns Hdu 4749 Parade Show (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
- POJ 3167 Cow Patterns 笔记
- POJMatrix(二维树状数组)
- POJ 2155 Matrix 二维树状数组
- poj_2352树状数组
- poj2155 树状数组
- poj 2029 Get Many Persimmon Trees 二维树状数组