Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <stack>
- #include <queue>
- #include <math.h>
- #include <string.h>
- #include <set>
- #include <map>
- #include <iostream>
- #include <sstream>
- #define MAXN 1007
- #define ull unsigned long long
- #define INF 0xffffff
- #define PI acos(-1)
- using namespace std;
- string mapper[256];
- ull C[MAXN*12], pot[MAXN*12];
- ull B1 = 33, B2 = 79;
- ull fastHash[MAXN*12];
- int test = 1;
- char str[1001], bin[MAXN*12];
- int n,m;
- //transforma int em binario
- string getBin(int v){
- string ans = "";
- if(v == 0) ans = "0";
- while(v > 0){
- ans = string(1, '0'+v%2)+ans;
- v /= 2;
- }
- while(ans.size() < 6){
- ans = "0"+ans;
- }
- return ans;
- }
- //pega o hash da janela
- ull getHash(int i, int j){
- return fastHash[j+1] - (fastHash[i] * pot[j-i+1]) + C[j-i+1];
- }
- //comparator pra imprimir a resposta
- bool comp (vector<int> i,vector<int> j){
- if(i.size() != j.size()){
- return i.size() < j.size();
- }else{
- return i < j;
- }
- }
- void printSubstring(int st){
- for(int i = st; i < st+m; i++){
- cout << bin[i];
- }
- cout << endl;
- }
- //Testa substrig que comecam em 'a' e 'b', com tamanhos T variaveis.
- //Pega o maior T em comum entre as duas substrings e verifica o proximo caractere
- bool lex(int a, int b){
- int lo = 0, hi = m;
- while(lo < hi){
- int T = (lo+hi+1) / 2;
- if(getHash(a,a+T-1) == getHash(b,b+T-1)){
- lo = T;
- }else{
- hi = T-1;
- }
- }
- //printSubstring(a) ;printSubstring(b);
- //cout << lo << " " << endl;
- if(bin[a+lo] < bin[b+lo]){
- return 0;
- }else{
- return 1;
- }
- }
- /*
- mapper -> guarda os numeros em binario no formatro string
- bin -> guarda a string ja em formato binario
- fastHash -> guarda hash da string atual
- */
- int main(void){
- //freopen("in.in", "r", stdin);
- int idx = 0;
- pot[0] = C[0] = 1;
- for(int i = 0; i < MAXN; i++){
- pot[i+1] = pot[i] * B1;
- C[i+1] = C[i] * B2;
- }
- for(int i = 'A'; i <= 'Z'; i++){
- mapper[i] = getBin(idx++);
- }
- for(int i = 'a'; i <= 'z'; i++){
- mapper[i] = getBin(idx++);
- }
- for(int i = '0'; i <= '9'; i++){
- mapper[i] = getBin(idx++);
- }
- mapper['+'] = getBin(idx++);
- mapper['/'] = getBin(idx++);
- while(scanf("%d", &n) && n != 0){
- map<string, vector<int> > ans;
- for(int i = 0; i < n; i++){
- //lendo a string em base64
- scanf(" %s", str);
- int size = strlen(str);
- m = size*6;
- int pos = 0;
- //Construindo a string binaria e ja prcessando o hash
- for(int j = 0; j < size; j++){
- for(int k = 0; k < mapper[str[j]].size(); k++){
- bin[pos] = mapper[str[j]][k];
- fastHash[pos+1] = mapper[str[j]][k] + fastHash[pos] * B1;
- pos++;
- }
- }
- //Duplicando a string binaria e ja prcessando o hash
- for(int j = 0; j < size; j++){
- for(int k = 0; k < mapper[str[j]].size(); k++){
- bin[pos] = mapper[str[j]][k];
- fastHash[pos+1] = mapper[str[j]][k] + fastHash[pos] * B1;
- pos++;
- }
- }
- int lower = 0;
- //pegando a menor, considerando que cada substring comeca em j e tem tamanho m
- for(int j = 1; j + m < m*2; j++){
- if(lex(lower,j) == 1){
- lower = j;
- }
- }
- //map pra agrupar os fingerprints
- string tmpAns = "";
- for(int j = lower; j < lower+m; j++) tmpAns += string(1, bin[j]);
- //cout << tmpAns << endl;
- if(ans.find(tmpAns) == ans.end()){
- ans[tmpAns] = vector<int>(1,i);
- }else{
- ans[tmpAns].push_back(i);
- }
- }
- printf("Case %d:\n", test++);
- vector<vector<int> > groups;
- for(map<string, vector<int> >::iterator it = ans.begin(); it != ans.end(); it++){
- sort(it->second.begin(), it->second.end());
- groups.push_back(it->second);
- }
- sort(groups.begin(), groups.end(), comp);
- for(int i = 0; i < groups.size(); i++){
- printf("%d",1+groups[i][0]);
- for(int j = 1; j < groups[i].size(); j++){
- printf(" %d", 1+groups[i][j]);
- }
- printf("\n");
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement