Cod sursa(job #2791543)

Utilizator Teodor94Teodor Plop Teodor94 Data 30 octombrie 2021 17:50:46
Problema Potrivirea sirurilor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.23 kb
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;

#define MAX_LENGTH 2000000

#define HASH_SIZE 10000007
#define HASH_BASE 123

char str[MAX_LENGTH + 1];
int strLength;

char pattern[MAX_LENGTH + 1];
int patternLength;

void eraseNewLine(char str[], int& length) {
  if (str[length - 1] == '\n')
    str[--length] = 0;
}

int lgput(int a, int n, int mod) {
  int p;

  p = 1;
  while (n) {
    if (n & 1)
      p = (long long)p * a % mod;
    a = (long long)a * a % mod;
    n >>= 1;
  }

  return p;
}

bool cmp(char str[], char pattern[]) {
  int i;

  i = 0;
  while (str[i] && pattern[i] && str[i] == pattern[i])
    ++i;

  return pattern[i] == 0;
}

int computeHash(char str[], int length) {
  int hash, i;

  hash = 0;
  i = 0;
  while (i < length) {
    hash = (hash * HASH_BASE + str[i]) % HASH_SIZE;
    ++i;
  }

  return hash;
}

int addToHash(int hash, char ch) {
  return (hash * HASH_BASE + ch) % HASH_SIZE;
}

int removeFromHash(int hash, char ch, int power) {
  hash -= ch * power % HASH_SIZE;
  if (hash < 0)
    hash += HASH_SIZE;
  return hash;
}

bool search(char str[], int strLength, char pattern[], int patternLength) {
  int i, patternHash, strHash, power;
  bool patternFound;

  patternHash = computeHash(pattern, patternLength);
  strHash = computeHash(str, patternLength - 1);

  power = lgput(HASH_BASE, patternLength - 1, HASH_SIZE);

  patternFound = false;
  i = patternLength;
  while (i <= strLength && !patternFound) {
    strHash = addToHash(strHash, str[i - 1]);
    patternFound = patternHash == strHash && cmp(str + i - patternLength, pattern);
    strHash = removeFromHash(strHash, str[i - patternLength], power);

    ++i;
  }

  return patternFound;
}

void searchAndPrint(FILE* fout, char str[], int strLength, char pattern[], int patternLength) {
  int i, patternHash, strHash, power;
  bool patternFound;
  vector<int> matchesFound;
  int noMatchesFound;

  patternHash = computeHash(pattern, patternLength);
  strHash = computeHash(str, patternLength - 1);

  power = lgput(HASH_BASE, patternLength - 1, HASH_SIZE);

  noMatchesFound = 0;
  patternFound = false;
  i = patternLength;
  while (i <= strLength) {
    strHash = addToHash(strHash, str[i - 1]);
    patternFound = patternHash == strHash;// && cmp(str + i - patternLength, pattern);
    strHash = removeFromHash(strHash, str[i - patternLength], power);

    if (patternFound) {
      if (matchesFound.size() < 1000)
        matchesFound.push_back(i - patternLength);
      ++noMatchesFound;
    }

    ++i;
  }

  fprintf(fout, "%d\n", noMatchesFound);
  for (auto match : matchesFound)
    fprintf(fout, "%d ", match);
}

int main() {
  FILE *fin, *fout;
  fin = fopen("strmatch.in", "r");
  fout = fopen("strmatch.out", "w");

  fgets(pattern, sizeof(pattern), fin);
  patternLength = strlen(pattern);
  eraseNewLine(pattern, patternLength);

  fgets(str, sizeof(str), fin);
  strLength = strlen(str);
  eraseNewLine(str, strLength);

  //fprintf(fout, "%d\n", search(str, strLength, pattern, patternLength));
  searchAndPrint(fout, str, strLength, pattern, patternLength);

  fclose(fin);
  fclose(fout);
  return 0;
}