1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
#include <iostream>
#include <cmath>
#define b2n63 9223372036854775808
using std::cin;
using std::cout;
using std::string;
short n, c, ptn, bb, tip, size;
unsigned long long bbb;
/*n - number of objects,
c - used as counter variable and insted of a parameter,
ptn - current number of paths,
tip - number of bytes in a part of flag set (number of bits in unsigned long long)
size - number of "tip's" that are in the flag "variable",
bb and bbb - counting variables*/
class juice
{ /*My objects with strings*/
public:
short k, kk, kc; //number of strings in it, counter variable, group of bytes used
string *s; //The array of strings
unsigned long long *p, kn; //pointer to flags and a flag currently used
void add(); /*constructor, and inserting strings*/
void compare(string d[], int f); /*Compare this object with another one and set the flag for it*/
short kon(unsigned long long *j, short *s); /*Returns details of the next object that can go after it*/
void clntext() { delete s; } /*Delete strings*/
~juice() { delete p; } /*Delete the flags*/
};
class put
{ /*My paths of objects*/
public:
short m; //How many flags it has
unsigned long long *t; //The flags
put *g; //Next element of the list
put(); /*constructor - sets things to zero*/
bool ok(unsigned long long tt[]); /*Return true if any of the flags match*/
~put() { delete t; delete g; } /*Delite the flag set and the next list element*/
};
juice *o; //Global variable
put *pp, *ep; //The beggining of the flag list, and the path currently in use
void putanja(short x);
int main()
{
short x, k; //counting variables
cin >> n; //How many objects
tip = 8 * sizeof(unsigned long long); //Set tip
size = (n-1)/tip + 1; //Set size
juice l[n]; //Make objects
o=l; //Make the objects globaly accesable
for(x=0; x!=n; x++)
{
cin >> c; //How many strings
l[x].add(); //Inster strings
}
for(x=0; x!=n; x++)
for(c=0; c!=n; c++)
{
if(x==c) continue; //Dont compare it with itself
l[x].compare(l[c].s, l[c].k); //Compare 2 objects and set flags
}
for(x=0; x!=n; x++) l[x].clntext(); //Delite strings
for(k=x=0; x!=n; x++, k += x%tip?0:1)
{
if(pp) { ep->g = new put; ep=ep->g; } //New path
else pp = ep = new put;
ptn++;
ep->t[k] = 1<<(x-tip*k); //Set first flag of the path
ep->m++; //increment the flag lenght
putanja(x); //Search for more elements for the path
}
for(k=0; k!=n; k++) //Displaying objects flags
{
cout << "\nE: ";
for(bb=0; bb!=size; bb++)
for(x=0; x!=n && x!=63; x++)
cout << ' ' << ((l[k].p[bb] & (1<<x))!=0);
} cout<<'\n';
for(ep=pp; ep; ep=ep->g) //Displaying path details
{
cout << "\nP: " << ep->m << " > t: ";
for(bb=0; bb!=size; bb++)
for(x=0; x!=n && x!=63; x++)
cout << ' ' << ((ep->t[bb] & (1<<x))!=0);
}
delete pp; //Delite the list
cin.get();cin.get();
return 0;
}
void putanja(short x)
{
put *p = ep; //Remember which path this is
unsigned long long j; //Counter var
short y, s; //More counters
for(y=o[x].kon(&j, &s); y!=-1; y=o[x].kon(&j, &s)) //Get a flag (it's details)
{
if(!(p->t[s] & j)) //If the element isn't already in ine path (I'm not realy sure do I need this)
{
ep->g = new put; //Make a new path and put it on the end of the list
ep = ep->g; //Switch to it
ptn++;
ep->m = p->m +1; //Set lenght
for(bb=0; bb!=size; bb++) ep->t[bb] = p->t[bb]; //Copy flags from previus path
ep->t[s] |= j; //Add new path
putanja(y); //Try to increse it's size again
}
}
return;
}
void juice::add()
{
k=c;
kk=-1;
kn=1;
kc=0;
s = new string[k];
p = new unsigned long long[size];
for(bb=0; bb!=size; bb++) p[bb]=0;
for(bb=0; bb!=k; bb++)
cin >> s[bb];
}
void juice::compare(string d[], int f)
{
if(f<=k) return; /*Skip if the other element dosen't have more string than this one*/
short u, j, t;
t = (c-1)/tip; //Select the flag "variable" part
bbb = 1<<(c-tip*t); //Select the flag
for(u=0; u!=k; u++)
{
for(j=bb=0; bb!=f; bb++)
if(!s[u].compare(d[bb])) { j++; break; }
if(!j) return; //Can't set the flag
}
p[t] |= bbb; //Tests passed, set the fag
return;
}
short juice::kon(unsigned long long *j, short *s)
{
bool b=1;
while(1)
{
kk++;
if(kn==b2n63) { kc++; kn=1; }
if(kk>=n) { kn=1; kc=0; kk=-1; return -1; }
if(p[kc] & kn) break;
kn <<= 1;
b=0;
}
*j = kn;
*s = kc;
if(b) kn <<= 1;
return kk;
}
put::put()
{
t = new unsigned long long[size];
m = 0;
g = NULL;
for(bb=0; bb!=size; bb++) t[bb]=0;
}
bool put::ok(unsigned long long tt[])
{
for(bb=0; bb!=size; bb++)
if(tt[bb] & t[bb]) return 0;
return 1;
}
|