POJ3167 Cow Patterns (KMP)

部署运行你感兴趣的模型镜像

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.

Sample Input

9 6 10
5
6
2
10
10
7
3
2
9
1
4
4
3
2
1

Sample Output

1
3

Hint

Explanation of the sample: 

The sample input corresponds to the example given in the problem statement. 

There is only one match, at position 3 within FJ's sequence of N cows.

Source

USACO 2005 December Gold


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MAXN = 100010;
const int MAXM = 25010;
int a[MAXN];
int b[MAXN];
int n, m, s;
int as[MAXN][30];
int bs[MAXM][30];

void init() { //预处理,计算当前数包含多少相同值的数 (s<=25,所以这里直接开了数组计算)
    for(int i = 0; i < n; ++i) {
        if(i ==0) {
            for(int j = 1; j <= 25; ++j) as[i][j] = 0;
        } else {
            for(int j = 1; j <= 25; ++j) as[i][j] = as[i-1][j];
        }
        as[i][a[i]]++;
    }
    for(int i = 0; i < m; ++i) {
        if(i ==0) {
            for(int j = 1; j <= 25; ++j) bs[i][j] = 0;
        } else {
            for(int j = 1; j <= 25; ++j) bs[i][j] = bs[i-1][j];
        }
        bs[i][b[i]]++;
    }
}

int next[MAXM];
void kmp_pre() {
    int i, j;
    j = next[0] = -1;
    i = 0;
    while(i < m) {
        int t11 = 0, t12 = 0, t21 = 0, t22 = 0;
        for(int k = 1; k < b[i]; k++) { //比b[i]小的数有多少
            if(i-j > 0) t11 += bs[i][k] - bs[i-j-1][k];
            else t11 += bs[i][k];
        }
        if(i-j > 0) t12 = bs[i][b[i]] - bs[i-j-1][b[i]];  //等于b[i]的数有多少
        else t12 = bs[i][b[i]];

        for(int k = 1; k < b[j]; k++) {  //比b[j]小的数有多少
            t21 += bs[j][k];
        }
        t22 = bs[j][b[j]];  //等于b[j]的数有多少
        if(j == -1 || (t11 == t21 && t12 == t22)) {
            next[++i] = ++j;
        } else {
            j = next[j];
        }
    }
}

vector<int>ans;
void kmp() {
    ans.clear();
    int i, j;
    kmp_pre();
    i = j = 0;
    while(i < n) {
        int t11 = 0, t12 = 0, t21 = 0, t22 = 0;
        for(int k = 1; k < a[i]; k++) {
            if(i-j > 0) t11 += as[i][k] - as[i-j-1][k];
            else t11 += as[i][k];
        }
        if(i-j > 0) t12 = as[i][a[i]] - as[i-j-1][a[i]];
        else t12 = as[i][a[i]];

        for(int k = 1; k < b[j]; k++) {
            t21 += bs[j][k];
        }
        t22 = bs[j][b[j]];
        if(j == -1 || (t11 == t21 && t12 == t22)) { //两个位置的数具有同等偏向关系取决于两个数的 比自身值小 和 等于自身值 这两个量相等
            i++; j++;
            if(j >= m) {
                ans.push_back(i-m+1);
                j = next[j];
            }
        } else {
            j = next[j];
        }
    }
}

int main()
{
    //freopen("out.txt", "w", stdout);
    //freopen("in.txt", "r", stdin);
    while(scanf("%d%d%d", &n, &m, &s) == 3) {
        for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
        for(int i = 0; i < m; ++i) scanf("%d", &b[i]);
        init();
        kmp();
        printf("%d\n", ans.size());
        for(int i = 0; i < ans.size(); ++i) {
            printf("%d\n", ans[i]);
        }
    }
    return 0;
}


您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### 解题思路 POJ 3613 Cow Relays 问题要求计算在给定的图中,从起点到终点恰好经过 $k$ 条边的最短路径。常规的暴力解法,即每次走一步更新最短路径,时间复杂度为 $O(k * n^3)$,效率较低。可利用二进制思想和矩阵快速幂的方法,将时间复杂度优化到 $O(logK * n^3)$ [^2]。 具体思路如下: 1. **图的表示**:使用邻接矩阵来表示图,矩阵中的元素 `mat[i][j]` 表示从节点 `i` 到节点 `j` 的最短距离,初始值设为无穷大 `INF`。 2. **矩阵乘法的定义**:普通矩阵乘法是对应元素相乘再相加,而这里定义的矩阵乘法是对应元素相加再取最小值。即 `C.mat[i][j] = min(C.mat[i][j], A.mat[i][k] + B.mat[k][j])`,表示从节点 `i` 经过节点 `k` 到节点 `j` 的最短距离。 3. **矩阵快速幂**:通过不断地将矩阵自乘,利用二进制的思想,快速计算出经过 $k$ 条边的最短路径矩阵。 4. **节点编号映射**:由于节点编号可能不连续,使用一个数组 `f` 来将原始节点编号映射到连续的编号,方便矩阵操作。 ### 代码实现 以下是实现该算法的 C++ 代码: ```cpp #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define INF ((1<<30)-1) int n; struct matrix { int mat[201][201]; matrix() { for(int i = 0; i < 201; i++) for(int j = 0; j < 201; j++) mat[i][j] = INF; } }; int f[2001]; matrix mul(matrix A, matrix B) { matrix C; int i, j, k; for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { for(k = 1; k <= n; k++) { C.mat[i][j] = min(C.mat[i][j], A.mat[i][k] + B.mat[k][j]); } } } return C; } matrix powmul(matrix A, int k) { matrix B; for(int i = 1; i <= n; i++) B.mat[i][i] = 0; while(k) { if(k & 1) B = mul(B, A); A = mul(A, A); k >>= 1; } return B; } int main() { matrix A; int k, t, s, e, a, b, c; scanf("%d%d%d%d", &k, &t, &s, &e); int num = 1; while(t--) { scanf("%d%d%d", &c, &a, &b); if(f[a] == 0) f[a] = num++; if(f[b] == 0) f[b] = num++; A.mat[f[a]][f[b]] = A.mat[f[b]][f[a]] = c; } n = num - 1; A = powmul(A, k); cout << A.mat[f[s]][f[e]] << endl; return 0; } ``` ### 代码解释 1. **结构体 `matrix`**:定义了一个矩阵结构体,用于存储图的邻接矩阵,构造函数将矩阵元素初始化为无穷大。 2. **函数 `mul`**:实现了自定义的矩阵乘法,计算两个矩阵相乘的结果。 3. **函数 `powmul`**:实现了矩阵快速幂,通过不断地将矩阵自乘,快速计算出经过 $k$ 条边的最短路径矩阵。 4. **主函数 `main`**:读取输入数据,将节点编号映射到连续的编号,初始化邻接矩阵,调用 `powmul` 函数计算经过 $k$ 条边的最短路径矩阵,最后输出从起点到终点的最短距离。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值