Cod sursa(job #1457316)

Utilizator tony.hegyesAntonius Cezar Hegyes tony.hegyes Data 3 iulie 2015 09:38:30
Problema Potrivirea sirurilor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.25 kb
#include <fstream>
#include <vector>
#include <iostream>
#include <cstring>
#include <iostream>
using namespace std;
 
 ///// DESCRIPTION
// THIS PROGRAM FINDS ALL OCCURENCES
// OF STRING A IN STRING B BY USING
// THE KMP ALGORITHM
/////

// !!! the MAXN number might be too big for 
// the stack of variables in main for local compilers
const int MAXN = 2000001; // max number of chars

int states[MAXN];

void prefixGenerator(char[], int, int[]);

int main(int argc, char **argv)
{
    // INPUT
	ifstream indata("strmatch.in");
	char A[MAXN], B[MAXN];
     
	indata >> A >> B;
	indata.close();
     
    // PATTERN MATCHING
	vector<int> positions;
	int n = strlen(A), m = strlen(B);
	
	//int states[n + 1];
	prefixGenerator(A, n, states);
	
	// do the automation
	for (int i = 0, curState = 0; i < m; i++) {
		// as long as we are not "expanding" the empty string
		// and we cannot expand, try the next "best"/longest candidate suffix
		while(curState > 0 && A[curState] != B[i]) {
			curState = states[curState];
		}
		
		// when we exited the while, check if the current chars match
		// (either expand the empty string, curState = 0, or the next "best" candidate
		if (A[curState] == B[i]) {
			curState++;
		}
		
		// well, one string made it to full length -- it's a match!!!
		if (curState == n) {
			curState = states[n]; // reset curState to 0, basically (usually)
			positions.push_back(i - n + 1); // the pattern starts at that index
		}
	}
     
    // OUTPUT
	ofstream outdata("strmatch.out");
	outdata << positions.size() << "\n";
	for (size_t i = 0; i < positions.size() && i < 1000; i++) {
		outdata << positions[i] << " ";
	}
	outdata.close();
	
	return 0;
}

void prefixGenerator(char A[], int n, int states[]) {
	states[0] = states[1] = 0; // always true
	
	for (int i = 2; i <= n; i++) {
		// the largest suffix/prefix before
		int q = states[i - 1];
		
		while(true) {
			// check if we can expand that prefix/suffix,
			// i.e. if the next char in prefix is can be 
			// "expanded" to the suffix
			if (A[q] == A[i - 1]) {
				states[i] = q + 1;
				break;
			}
			
			// if that was the empty string
			// that we couldn't expand
			if (q == 0) {
				states[i] = 0;
				break;
			}
			
			// otherwise, try to "expand"
			// the next "best" candidates
			q = states[q];
		}
	}
}