Hashowanie problem z porównywaniem słów

0

Witam.
Mam za takie zadanie.
Podane N gdzie N to długość słowa, potem samo słowo, podają mi M jest to ilość zapytań. W każdym zapytaniu podają mi przedział o parzystej długości i pytają się czy jest to słowo podwójne np. bacbac , cc ,abab.
Przykład wejścia.
10
abbacbacca
5
1 4
3 8
5 8
8 9
1 10
poprawnym wynikiem jest:

NIE
TAK
NIE
TAK
NIE
Słowa występujące w kolejnych zapytaniach to: abba, bacbac, cbac, cc, abbacbacca.

Napisałem program który hashuje całe słowo od strony prefiksu (od lewej) i napisałem funkcje która porównuje słowa , jednakże jest problem. Program się wali kiedy long long obcina nam wartość hasha . Moze mi ktos pomoc ?

 #include <iostream>
#include <math.h>
#define MX 1000005
using namespace std;
long long int w_hash[MX];
int X = 3;
int hash(int a, int b)
{
    long long int wynik=ceil((w_hash[b]-w_hash[a-1])/pow(X,a));
    return wynik;
}
int main()
{
 int n;
 cin>>n;
 char * tab = new char [n];
 for(int i = 0 ; i < n;i++)cin>>tab[i];
 w_hash[0]=tab[0]-96;
 for(int i = 1 ; i < n ; i++)w_hash[i]=w_hash[i-1]+((tab[i]-96)*pow(X,i));
 int t;
 cin>>t;
 for(int i = 0 ; i < t;i++)
 {
     int a, b;
     cin>>a>>b;
     int zakres=ceil(a+(b-a+1)/2)-2;
     //cout<<a-1<< " " <<zakres<< " " <<b-1<< " "<<hash(a-1,zakres)<< " "<<hash(zakres+1,b-1)<<endl;
     if(hash(a-1,zakres)==hash(zakres+1,b-1))cout<<"TAK\n";
     else cout<<"NIE\n";

 }
 return 0;
}

PS: nie bawiłem się jeszcze w preprocesnig potęgowy ani szybkie potęgowanie więc proszę o tym nie wspominać ;)

0

pow(X,i) - to dla X = 3 możesz obliczyć tylko do i = 40 jeżeli wynik będziesz następnie przechowywał w zmiennej long long.

0

Czy przypadkiem long long nie zacznie obcinać dalej ? Jak sobie z tym poradzić ?!

0

Wymyśl inny algorytm, może zrób podobny preprocessing jak w liniowym szukaniu palindromów, lub przez drzewo sufiksowe (nie wiem, czy to będzie działać, nie chce mi się nad tym myśleć, daje sugestię co działa w podobnych sytuacjach). Pow i tak jest ograniczony do zmiennej double (lub ewentualnie long double), nieograniczonej dokładności nie uzyskasz, chyba że skorzystasz z GMP, czy samemu napiszesz liczby całkowite o nieograniczonej precyzji (ale nie wiadomo, czy to będzie miało odpowiednią wydajność).

0

Problem rozwiązwany, może komuś sięto przyda, w książe "Algorytmy i struktury danych" jest algorytm działający w czasie O(n log n).
dzięki za odpowiedź:)

0

Znam to jednak tamten algorytm dziakła w czasie O(n^2) a ja mam n <= 1.000.000 :)

0

chyba do końca nie doczytałeś

0

Chodzi o to że właśnie przeczytałem i z tego co rozumiem to wychodzi na to że dla każdego zapytania muszę liczyć od nowa wszystko, chyba że z raz policzonej tablicy P[] mogę w czasie stałym wyciągać zapytania o przedział.

Może mi ktoś to wyjaśnić jakby to mialo dzialac ?

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