#include <iostream> #include <vector> #include <cstring> using namespace std; #define REP(x,n) for(int x=0;x<(n);++x) #define FOR(a,b,e) for(int a=b;a<=(e);++a) int n, m; const int MAX_N = 501; const int MAX_M = 1001; vector<int> H[MAX_N]; int S[MAX_M]; class CHash { const long long BASE = 1000000007; const long long p = 2011; vector<long long> pp; public: CHash(int n_max) { pp.resize(n_max + 1); pp[0] = 1; REP(x, n_max) pp[x + 1] = pp[x] * p % BASE; } void create(int* in, long long* out, int n) { out[0] = 0; REP(x, n) out[x + 1] = ((out[x] * p) + in[x]) % BASE; } long long slice(long long* in, int begin, int end) { long long ret = (in[end] - in[begin]*pp[end-begin]) % BASE; return ret < 0 ? ret + BASE : ret; } long long equals(long long h1, long long h2) { return (h1 - h2) % BASE == 0; } }; const int MAX_HASH = 15000001; long long h[MAX_HASH]; int evolve[2][MAX_HASH]; long long hashS; #define RETURN(n) {cout<<n<<endl;return 0;} int main() { ios_base::sync_with_stdio(0); cin >> n >> m; CHash hash(MAX_N); int l; FOR(x, 1, n) { cin >> l; vector<int>& Hx = H[x]; Hx.resize(l); REP(y, l) cin >> Hx[y]; } REP(x, m) cin >> S[x]; // cerr << "Szukany ciag: "<<endl; // REP(x,m) // cerr<<S[x]<<" "; // cerr << endl; hash.create(S, h, m); hashS = hash.slice(h, 0, m); evolve[0][0] = 1; int len = 1, newLen; REP(x, n) { // cerr << "Krok " << x+1 << endl; // REP(y,len) // cerr << evolve[x&1][y] << " "; // cerr << endl; hash.create(evolve[x & 1], h, len); REP(y, len - m) { long long subhash = hash.slice(h, y, y + m); if (hash.equals(subhash, hashS)) RETURN(x + 1); } newLen = 0; REP(y, len) { vector<int>& Hx = H[evolve[x & 1][y]]; if(newLen+Hx.size() >= MAX_HASH) { // cerr<<"Krok "<<x+1<<" - nie znaleziono" << endl; RETURN(-1); } memcpy(&evolve[(~x) & 1][newLen], &Hx[0], (Hx.size() << 2)); newLen += Hx.size(); } len = newLen; } RETURN(-1); return 0; }
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 | #include <iostream> #include <vector> #include <cstring> using namespace std; #define REP(x,n) for(int x=0;x<(n);++x) #define FOR(a,b,e) for(int a=b;a<=(e);++a) int n, m; const int MAX_N = 501; const int MAX_M = 1001; vector<int> H[MAX_N]; int S[MAX_M]; class CHash { const long long BASE = 1000000007; const long long p = 2011; vector<long long> pp; public: CHash(int n_max) { pp.resize(n_max + 1); pp[0] = 1; REP(x, n_max) pp[x + 1] = pp[x] * p % BASE; } void create(int* in, long long* out, int n) { out[0] = 0; REP(x, n) out[x + 1] = ((out[x] * p) + in[x]) % BASE; } long long slice(long long* in, int begin, int end) { long long ret = (in[end] - in[begin]*pp[end-begin]) % BASE; return ret < 0 ? ret + BASE : ret; } long long equals(long long h1, long long h2) { return (h1 - h2) % BASE == 0; } }; const int MAX_HASH = 15000001; long long h[MAX_HASH]; int evolve[2][MAX_HASH]; long long hashS; #define RETURN(n) {cout<<n<<endl;return 0;} int main() { ios_base::sync_with_stdio(0); cin >> n >> m; CHash hash(MAX_N); int l; FOR(x, 1, n) { cin >> l; vector<int>& Hx = H[x]; Hx.resize(l); REP(y, l) cin >> Hx[y]; } REP(x, m) cin >> S[x]; // cerr << "Szukany ciag: "<<endl; // REP(x,m) // cerr<<S[x]<<" "; // cerr << endl; hash.create(S, h, m); hashS = hash.slice(h, 0, m); evolve[0][0] = 1; int len = 1, newLen; REP(x, n) { // cerr << "Krok " << x+1 << endl; // REP(y,len) // cerr << evolve[x&1][y] << " "; // cerr << endl; hash.create(evolve[x & 1], h, len); REP(y, len - m) { long long subhash = hash.slice(h, y, y + m); if (hash.equals(subhash, hashS)) RETURN(x + 1); } newLen = 0; REP(y, len) { vector<int>& Hx = H[evolve[x & 1][y]]; if(newLen+Hx.size() >= MAX_HASH) { // cerr<<"Krok "<<x+1<<" - nie znaleziono" << endl; RETURN(-1); } memcpy(&evolve[(~x) & 1][newLen], &Hx[0], (Hx.size() << 2)); newLen += Hx.size(); } len = newLen; } RETURN(-1); return 0; } |