Cod sursa(job #672230)

Utilizator ukiandreaAndreea Lucau ukiandrea Data 1 februarie 2012 19:28:51
Problema Potrivirea sirurilor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.45 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <vector>

#define MAX_STRING_SIZE     2000000

char a[MAX_STRING_SIZE + 1];
char b[MAX_STRING_SIZE + 1];
int *t;

// ----------- BRUTE FORCE -------------
void find_match_hard()
{
    std::vector<int> apps;

    if (strlen(b) < strlen(a)) {
        printf("0\n");
        return;
    }

    for (unsigned int i = 0; i <= (strlen(b) - strlen(a)); i++) {
        if (memcmp(&b[i], a, strlen(a)) == 0) {
            apps.push_back(i);
        }
    }

    printf("%d\n", apps.size());
    for (std::vector<int>::iterator it = apps.begin(); it != apps.end(); ++it)
        printf("%d ", *it);

    printf("\n");
}
// ----------- END BRUTE FORCE -------------


// ----------- KMP ------------------------
void build_kmp_table()
{
    // t[i] - the amount of backtraking required if there isn't a match
    //      - the length of the longest possible initial segment of W leading up to (but not including) that position
    t = (int *)calloc(strlen(a), sizeof(int));
    t[0] = -1;
    t[1] = 0;

    int pos = 2, cnd = 0;

    while (pos < strlen(a)) {
        if (a[pos - 1] == a[cnd]) {
            cnd++;
            t[pos] = cnd;
            pos++;
        } else {
            if (cnd) {
                cnd = t[cnd];
            } else {
                t[pos] = 0;
                pos++;
            }
        }
    }
}

void find_match_kmp()
{
    std::vector<int> apps;

    if (strlen(b) < strlen(a)) {
        printf("0\n");
        return;
    }

    int m = 0, i = 0;

    build_kmp_table();

    while ((m + i) < strlen(b)) {
        if (a[i] == b[m + i]) {
            if (i == (strlen(a)- 1)) {
                apps.push_back(m);
                m = m + i - t[i];
                if (t[i] == -1)
                    i = 0;
                else 
                    i = t[i];
            } else
                i++;
        } else {
            m = m + i - t[i];
            if (t[i] != -1) {
                i = t[i];
            } else
                i = 0;
        }
    }

    printf("%d\n", apps.size());
    for (int i = 0; (i < 1000 && i < apps.size()); i++)
        printf("%d ", apps[i]);

    printf("\n");

    free(t);
}
// ----------- END KMP ------------------------


int main()
{
    freopen("strmatch.in", "r", stdin);
    freopen("strmatch.out", "w", stdout);

    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));

    scanf("%s\n", a);
    scanf("%s\n", b);

    find_match_kmp();

    return 0;
}