Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define FAST_ALLOCATOR_MEMORY 2e8
- //#define _GLIBCXX_DEBUG
- #include <bits/stdc++.h>
- /**
- * Author: Sergey Kopeliovich (Burunduk30@gmail.com)
- */
- #define VERSION "0.1.5"
- #include <cassert>
- #include <cstdio>
- #include <algorithm>
- /** Fast allocation */
- #ifdef FAST_ALLOCATOR_MEMORY
- int allocator_pos = 0;
- char allocator_memory[(int)FAST_ALLOCATOR_MEMORY];
- inline void * operator new ( size_t n ) {
- char *res = allocator_memory + allocator_pos;
- allocator_pos += n;
- assert(allocator_pos <= (int)FAST_ALLOCATOR_MEMORY);
- return (void *)res;
- }
- inline void operator delete ( void * ) noexcept { }
- //inline void * operator new [] ( size_t ) { assert(0); }
- //inline void operator delete [] ( void * ) { assert(0); }
- #endif
- /** Fast input-output */
- template <class T = int> inline T readInt();
- inline double readDouble();
- inline int readUInt();
- inline int readChar(); // first non-blank character
- inline void readWord( char *s );
- inline bool readLine( char *s ); // do not save '\n'
- inline bool isEof();
- inline int getChar();
- inline int peekChar();
- inline bool seekEof();
- inline void skipBlanks();
- template <class T> inline void writeInt( T x, char end = 0, int len = -1 );
- inline void writeChar( int x );
- inline void writeWord( const char *s );
- inline void writeDouble( double x, int len = 0 ); // works correct only for |x| < 2^{63}
- inline void flush();
- static struct buffer_flusher_t {
- ~buffer_flusher_t() {
- flush();
- }
- } buffer_flusher;
- /** Read */
- static const int buf_size = 4096;
- static unsigned char buf[buf_size];
- static int buf_len = 0, buf_pos = 0;
- inline bool isEof() {
- if (buf_pos == buf_len) {
- buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
- if (buf_pos == buf_len)
- return 1;
- }
- return 0;
- }
- inline int getChar() {
- return isEof() ? -1 : buf[buf_pos++];
- }
- inline int peekChar() {
- return isEof() ? -1 : buf[buf_pos];
- }
- inline bool seekEof() {
- int c;
- while ((c = peekChar()) != -1 && c <= 32)
- buf_pos++;
- return c == -1;
- }
- inline void skipBlanks() {
- while (!isEof() && buf[buf_pos] <= 32U)
- buf_pos++;
- }
- inline int readChar() {
- int c = getChar();
- while (c != -1 && c <= 32)
- c = getChar();
- return c;
- }
- inline int readUInt() {
- int c = readChar(), x = 0;
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- return x;
- }
- template <class T>
- inline T readInt() {
- int s = 1, c = readChar();
- T x = 0;
- if (c == '-')
- s = -1, c = getChar();
- else if (c == '+')
- c = getChar();
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- return s == 1 ? x : -x;
- }
- inline double readDouble() {
- int s = 1, c = readChar();
- double x = 0;
- if (c == '-')
- s = -1, c = getChar();
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- if (c == '.') {
- c = getChar();
- double coef = 1;
- while ('0' <= c && c <= '9')
- x += (c - '0') * (coef *= 1e-1), c = getChar();
- }
- return s == 1 ? x : -x;
- }
- inline void readWord( char *s ) {
- int c = readChar();
- while (c > 32)
- *s++ = c, c = getChar();
- *s = 0;
- }
- inline bool readLine( char *s ) {
- int c = getChar();
- while (c != '\n' && c != -1)
- *s++ = c, c = getChar();
- *s = 0;
- return c != -1;
- }
- /** Write */
- static int write_buf_pos = 0;
- static char write_buf[buf_size];
- inline void writeChar( int x ) {
- if (write_buf_pos == buf_size)
- fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
- write_buf[write_buf_pos++] = x;
- }
- inline void flush() {
- if (write_buf_pos) {
- fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
- fflush(stdout);
- }
- }
- template <class T>
- inline void writeInt( T x, char end, int output_len ) {
- if (x < 0)
- writeChar('-'), x = -x;
- char s[24];
- int n = 0;
- while (x || !n)
- s[n++] = '0' + x % 10, x /= 10;
- while (n < output_len)
- s[n++] = '0';
- while (n--)
- writeChar(s[n]);
- if (end)
- writeChar(end);
- }
- inline void writeWord( const char *s ) {
- while (*s)
- writeChar(*s++);
- }
- inline void writeDouble( double x, int output_len ) {
- if (x < 0)
- writeChar('-'), x = -x;
- assert(x <= (1LLU << 63) - 1);
- long long t = (long long)x;
- writeInt(t), x -= t;
- writeChar('.');
- for (int i = output_len - 1; i > 0; i--) {
- x *= 10;
- t = std::min(9, (int)x);
- writeChar('0' + t), x -= t;
- }
- x *= 10;
- t = std::min(9, (int)(x + 0.5));
- writeChar('0' + t);
- }
- #pragma GCC optimize("O3")
- #define chervyak 6
- #define sasha chervyak
- #define y1 jhgfds
- #define rank zhimba
- //#define count zashodeda
- #define prev maAslo
- #define hash akakzhit
- #define ll long long
- //#define int long long
- //#define ull uint64_t
- #define ld long double
- #define pb push_back
- #define eb emplace_back
- #define all(v) v.begin(), v.end()
- #define rep(i, n) for(int i = 0; i < n; i++)
- using namespace std;
- //freopen("input.txt", "r", stdin);
- //freopen("output.txt", "w", stdout);
- //cout << clock()*1000/CLOCKS_PER_SEC << '\n';
- //mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
- const int N = 3e5 + 5;
- const ll p = 37;
- const ll mod = 1000000007;
- int len;
- int cur = 1;
- const unsigned SZ = 500153;
- pair<pair<int,int>,pair<int,int>> hash_from[SZ];
- pair<pair<int,int>,pair<int,int>> hash_from_rev[SZ];
- // {hsh, cur} -> {d; u}
- bool fnd;
- unsigned pos(int x){
- unsigned i = x % SZ;
- while(hash_from[i].first.second == cur && hash_from[i].first.first != x && hash_from[i].first.first != 0){
- if(++i == SZ) i = 0;
- }
- fnd = false;
- if(hash_from[i].first.second == cur && hash_from[i].first.first == x) fnd = true;
- return i;
- }
- void ins(int x, pair<int,int> val){
- hash_from[pos(x)] = {{x, cur}, val};
- }
- bool fnd_rev;
- unsigned pos_rev(int x){
- unsigned i = x % SZ;
- while(hash_from_rev[i].first.second == cur && hash_from_rev[i].first.first != x && hash_from_rev[i].first.first != 0){
- if(++i == SZ) i = 0;
- }
- fnd_rev = false;
- if(hash_from_rev[i].first.second == cur && hash_from_rev[i].first.first == x) fnd_rev = true;
- return i;
- }
- ll pw[N];
- void ins_rev(int x, pair<int,int> val){
- x = (pw[len-val.first] * x) % mod;
- hash_from_rev[pos_rev(x)] = {{x, cur}, val};
- }
- vector<pair<int,char>> g[N];
- vector<int> d;
- vector<int> par;
- vector<pair<ll,pair<int,int>>> hashes;
- vector<pair<ll,pair<int,int>>> hashes_rev;
- ll h;
- void write_ans(int v, int u){
- //cout << "YES\n" << v+1 << ' ' << u+1 << '\n';
- writeWord("YES\n"), writeInt(v+1, ' '), writeInt(u+1, '\n');
- exit(0);
- }
- void test_podderevo(int v, int u, int parent, int hsh, int hshrev, int ddd){
- hashes.pb({hsh, {ddd, u}});
- hashes_rev.pb({hshrev, {ddd, u}});
- if(ddd <= len){
- int cur_hash = (pw[len - ddd] * hshrev) % mod;
- int hsh_ost = h - cur_hash + mod;
- if(hsh_ost >= mod) hsh_ost -= mod;
- unsigned ps = pos(hsh_ost);
- if(fnd){
- pair<int,int> ddd_other = hash_from[ps].second;
- if(ddd_other.first == len - ddd){
- write_ans(ddd_other.second, u);
- }
- }
- int cur_hash_rev = hsh;
- int hsh_ost_rev = h - cur_hash_rev + mod;
- if(hsh_ost_rev >= mod) hsh_ost_rev -= mod;
- unsigned ps_rev = pos_rev(hsh_ost_rev);
- if(fnd_rev){
- pair<int,int> ddd_other = hash_from_rev[ps_rev].second;
- if(ddd_other.first == len - ddd){
- write_ans(ddd_other.second, u);
- }
- }
- }else return;
- for(pair<int,char> xc : g[u]){
- int x = xc.first; char c = xc.second;
- if(d[x] == -1 && x != parent){
- int chr = c - 'a' + 1;
- test_podderevo(v, x, u, (p * hsh + chr) % mod, (pw[ddd] * chr + hshrev) % mod, ddd+1);
- }
- }
- }
- void test_hash(int v){
- ins(0, make_pair(0, v));
- ins_rev(0, make_pair(0, v));
- for(pair<int,char> xc : g[v]){
- int x = xc.first; char c = xc.second;
- if(d[x] == -1){
- unsigned ps = pos(h);
- if(fnd){
- pair<int,int> ddd_other = hash_from[ps].second;
- if(ddd_other.first == len){
- write_ans(ddd_other.second, v);
- }
- }
- unsigned ps_rev = pos_rev(h);
- if(fnd_rev){
- pair<int,int> ddd_other = hash_from_rev[ps_rev].second;
- if(ddd_other.first == len){
- write_ans(ddd_other.second, v);
- }
- }
- hashes.clear();
- hashes_rev.clear();
- int chr = c - 'a' + 1;
- test_podderevo(v, x, v, chr, chr, 1);
- for(pair<int,pair<int,int>> af : hashes) ins(af.first, af.second);
- for(pair<int,pair<int,int>> af : hashes_rev) ins_rev(af.first, af.second);
- }
- }
- }
- int get_centroid(int v, int parent, int n, int ¢roid){
- int size = 1;
- for(pair<int,char> xw : g[v]){
- int x = xw.first;
- if(x != parent && d[x] == -1){
- size += get_centroid(x, v, n, centroid);
- }
- }
- if(size * 2 >= n && centroid == -1) centroid = v;
- return size;
- }
- void build(int v, int parent, int depth, int n){
- int centroid = -1;
- get_centroid(v, -1, n, centroid);
- if(centroid == -1) centroid = v;
- d[centroid] = depth, par[centroid] = parent;
- ++cur;
- test_hash(centroid);
- for(pair<int,char> xw : g[centroid]){
- int x = xw.first;
- if(d[x] == -1){
- build(x, centroid, depth + 1, (n+1)/2);
- }
- }
- }
- int n;
- char* s;
- //string s;
- void solve(){
- h = 0;
- rep(i, len){
- int chr = s[i] - 'a' + 1;
- h = (pw[i] * chr + h) % mod;
- }
- d.assign(n, -1);
- par.assign(n, -1);
- build(0, -1, 0, n);
- }
- int32_t main(){
- ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
- //cin >> s; len = s.length();
- s = new char[N]; readWord(s); len = strlen(s);
- //cin >> n;
- n = readInt();
- rep(i, n-1){
- int x, y;
- char c;
- //cin >> x >> y >> c;
- x = readInt(), y = readInt(), c = readChar();
- --x, --y;
- g[x].eb(y, c);
- g[y].eb(x, c);
- }
- pw[0] = 1;
- rep(i, max(n,len)+1){
- pw[i+1] = (pw[i] * p) % mod;
- }
- hashes.reserve(n);
- hashes_rev.reserve(n);
- solve();
- //cout << "NO\n";
- writeWord("NO\n");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement