rabin-karp implementacja

0

Program za pomocą algorytmu rabina-karpa odnajduje wzorce w pliku z kluczami w pliku z tekstem. Po czym zamienia wszystkie małe litery odnalezionego wzorca w tekście na duże. Niestety program działa tylko dla wzorców o długości nie przekraczającej 3 znaków. Czy ktoś widzi dlaczego? ...

//wczytuje plik z tekstem i plik ze slowami kluczowymi, a nastepnie
//zamienia wszystkie slowa kluczowe odszukane w tekscie na duze litery
#include<iostream>
#include<string>
#include<fstream>
#include<cctype>
#include<cstdlib>
using namespace std;

int rabinkarp(string& plik, const string& wz);
     

int main()
{
    const int MAX_FILE_NAME=30;
    ifstream plik_in, plik_key;
    ofstream plik_out;
    string dane,dane_key,wzorzec,line;
    char nazwa_in[MAX_FILE_NAME],nazwa_key[MAX_FILE_NAME];
    cout<<"Podaj nazwe pliku ze slowani kluczowymi: ";
    cin>>nazwa_key;
    plik_key.open(nazwa_key);
    if (!plik_key){
                  cerr<<"Niepowodzenie podczas otwierania pliku!"<<endl;
                  system("pause");
                  return EXIT_FAILURE;
    }
    cout<<"Podaj nazwe pliku z tekstem: ";
    cin>>nazwa_in;
    plik_in.open(nazwa_in);
    if (!plik_in){
                  cerr<<"Niepowodzenie podczas otwierania pliku!"<<endl;
                  system("pause");
                  return EXIT_FAILURE;
    }
    while(getline(plik_in,line)) dane+=line+"\n"; 
    while(getline(plik_key,wzorzec)) 
      cout<<"Znaleziono "<<rabinkarp(dane,wzorzec)<<" wzorcow "<<wzorzec<<endl;
    plik_in.close();
    plik_key.close();
    plik_out.open(nazwa_in);
    plik_out<<dane;
    plik_out.close();
    system("pause");
    return EXIT_SUCCESS;
    
}

int rabinkarp(string& plik, const string& wz) {
	int h=1,p=0,t=0,ilosc=0;
	const int q=257; 
	const int d=256; 
	long n=plik.size();
	long m=wz.size();
	long i,j,k;
	for(i=1;i<m;i++) h*=d%q;
	for (i=0;i<m;i++) {
		p=(d*p+wz[i])%q;
	    t=(d*t+plik[i])%q;
	}         
    for (i=0;i<n-m;i++) {
		if (p==t) {
             j=0;
             while(tolower(wz[j])==tolower(plik[i+j++])){
               if(j==m){
                 ilosc++;
                 for(k=0;k<m;k++) plik[i+k]=toupper(plik[i+k]);
                 break;
               }
             }
        }
		t=((d*(t-tolower(plik[i])*h)+tolower(plik[i+m]))%q+q)%q;
	}
	return ilosc;
}
0

to nie moze byc przyczyna bledu o ktory pytasz, ale..

while(tolower(wz[j])==tolower(plik[i+j++]))

ta konstrukcja nie jest prawidlowa. nie masz gwarancji ze najpierw wykona sie wz[j] a dopiero potem plik[..j++]. rownie dobrze j++ moze wykonac sie pierwsze, zwlaszcza gdy np, przeniesiesz sie na inny kompilator np. visual<->g++

0

Po głębszym zastanowieniu stwierdzam, że masz rację :)
Na szczęście jednak mój kompilator robił to dokładnie tak jak chciałem. Jednak jest to drobna poprawka, nadal nie wiem czemu tak się dzieje...
Dzięki jednak za uwagę.

0

To też pewnie nie to, ale

h*=d%q;

jest równoważne

h*=(d%q);

a nie

h*=d;
h%=q;

(chodzi o: for(i=1;i<m;i++) h*=d%q;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1