您的位置:首页 > 其它

POJ 3167 Cow Patterns(模式串浮动匹配)

2015-04-30 14:18 375 查看
题目链接:http://poj.org/problem?id=3167

题意:模式串可以浮动的模式匹配问题给出模式串的相对大小,需要找出模式串匹配次数和位置。

思路:统计比当前数小,和于当前数相等的,然后进行kmp。

比如说模式串:1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9,那么2,10,10,7,3,2就是匹配的

code:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN = 100005;
const int MAXM = 25005;

int a[MAXN];        // 存放主串
int b[MAXM];        // 存放模式串
int as[MAXN][30];   // as[i][j] = k表示0 - i位中有k个数字j
int bs[MAXM][30];   // bs[i][j] = k表示0 - i位中有k个数字j
int next[MAXM];     // 存放模式串失配时的移动位数
vector<int> ans;    // 存放结果
int n, m, s;

void Init()
{
ans.clear();
memset(as, 0, sizeof(as));
memset(bs, 0, sizeof(bs));
as[1][a[1]] = 1;
bs[1][b[1]] = 1;
for (int i = 2; i <= n; ++i)
{
memcpy(as[i], as[i - 1], sizeof(as[0]));
++as[i][a[i]];
}
for (int i = 2; i <= m; ++i)
{
memcpy(bs[i], bs[i - 1], sizeof(bs[0]));
++bs[i][b[i]];
}
}

void GetNext()
{
memset(next, 0, sizeof(next));
int i = 1, j = 0, k = 0;
next[1] = 0;
while (i <= m)
{
int si = 0, sj = 0, ei = 0, ej = 0;
for (k = 1; k < b[i]; ++k)
si += bs[i][k] - bs[i - j][k];
ei = bs[i][k] - bs[i - j][k];
for (k = 1; k < b[j]; ++k)
sj += bs[j][k];
ej = bs[j][k];
if (0 == j || (si == sj && ei == ej)) next[++i] = ++j;
else j = next[j];
}
}

void Kmp()
{
int i = 1, j = 1, k = 1;
while (i <= n)
{
int si = 0, sj = 0, ei = 0, ej = 0;
for (k = 1; k < a[i]; ++k)
si += as[i][k] - as[i - j][k];
ei = as[i][k] - as[i - j][k];
for (k = 1; k < b[j]; ++k)
sj += bs[j][k];
ej = bs[j][k];
if (0 == j || (si == sj && ei == ej)) ++i, ++j;
else j = next[j];
if (j == m + 1)
{
ans.push_back(i - m);
j = next[j];
}
}
}

int main()
{
while (scanf("%d %d %d", &n, &m, &s) == 3)
{
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= m; ++i) scanf("%d", &b[i]);
Init();
GetNext();
Kmp();
size_t len = ans.size();
printf("%d\n", len);
for (size_t i = 0; i < len; ++i) printf("%d\n", ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: