Problem:
replace
Problem Statement
文字列
S
が与えられる．
以下の処理を
Q
個順番に行う．
S
に含まれる文字
c_i
を全て同時に文字列
p_i
で置き換える．
最後に文字列
S
の
A
文字目から
B
文字目まで(1-indexed)を出力せよ．
Input
入力は以下の形式に従う．与えられる数は全て整数である．
S
Q
A
B
c_1
p_1
...
c_Q
p_Q
Constraints
1≦Q≦3 \times 10^5
1≦A≦B≦10^{18}
B-A≦10^5
1≦|S|≦10
1≦|p_i|≦10
S
は小文字のアルファベットからなる文字列である．
c_i
は小文字のアルファベット1文字である．
p_i
は"."(ピリオド)1文字または小文字のアルファベットからなる文字列である．
p_i=
"."(ピリオド)のとき，
p_i
は空文字列として扱いなさい．
Output
Q
個の処理を順に行った後，
B
が
|S|
よりも大きかったときは"."(ピリオド)を1行に出力せよ．
それ以外のときは文字列
S
の
A
文字目から
B
文字目まで(1-indexed)を出力せよ．
Sample Input 1
abaz
3 1 5
a cab
b .
c x
Output for the Sample Input 1
xaxaz
文字列
S
は，abaz → cabbcabz → cacaz → xaxazと変化する．
Sample Input 2
original
1 2 5
x notchange
Output for the Sample Input 2
rigi
Sample Input 3
aaaa
2 1 1
a .
a nothing
Output for the Sample Input 3
.

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <map>
using namespace std;

struct NODE{
	char var;
	vector<NODE*> ch;
};

NODE *nowTarget[128];
NODE id[400000*10];

int pool = 0;
NODE* next(char c){
	id[pool].var = c;
	return &id[pool++];
}
void chg(char c,string s){
	if( s == "." ){
		NODE *u = nowTarget[c];
		u->var = '.';
		nowTarget[c] = next(c);
	}else{
		NODE *u = nowTarget[c];
		u->var = '.';
		nowTarget[c] = next(c);
		for(int i = 0 ; i < s.size() ; i++){
			u->ch.push_back(nowTarget[s[i]]);
		}
	}
}
map<NODE*,long long> memo;

#define INF (2000000000000000000ll)
long long cnt(NODE *r){
	if( memo.count(r) ) return memo[r];
	if( r->ch.size() == 0 ){
		return r->var=='.'?0:1;
	}else{
		long long res = 0;
		for(int i = 0 ; i < r->ch.size() ; i++)
			res = min(INF,res+cnt(r->ch[i]));
		return memo[r] = res;
	}
}

long long A,B;
string res;
void func(NODE *r,long long now){
	if( now + cnt(r) <= A ) return;
	if( now >= B ) return;
	
	if( r->ch.size() == 0 ){
		if( r->var != '.'){
			res += r->var;
		}
		return;
	}else{
		for(int i = 0 ; i < r->ch.size() ; i++){
			func(r->ch[i],now);
			now = min(INF,now+cnt(r->ch[i]));
		}
	}
}

int main(){
	string S;
	cin >> S;
	for(int i = 0 ; i < 128 ; i++)
		nowTarget[i] = next(i);
	NODE *root = nowTarget['.'];
	chg('.',S);
	
	int Q;
	cin >> Q >> A >> B;
	while(Q--){
		char c;
		string p;
		cin >> c >> p;
		chg(c,p);
	}
	--A;
	if( cnt(root) < B ){
		cout << "." << endl;
	}else{
		func(root,0);
		cout << res << endl;
	}
}
accuracy: 0.2857142857142857
time_ms: 390
memory_kb: 176568
final_rank: 6

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <climits>
#include <algorithm>
#include <cctype>
#include <cstdlib>
using namespace std;

typedef long long LL;

const LL inf = LLONG_MAX / 2;

struct node{
	char ch;
	LL refcnt;
	LL len;
	vector<node*> to;
	
	node(char c, LL r = 0, LL len = -1)
	: ch(c), refcnt(r), len(len) {}
};

struct state{
	int stnum;
	node *nd;
	LL a, b;
	size_t cntr;
	
	state(int s, node *nd, LL a, LL b, size_t c)
	: stnum(s), nd(nd), a(a), b(b), cntr(c) {}
};

node *alp[26];
node emp(0, inf, 0);
string ans;

node *getnode(int c){
	if(c == '.'){ return &emp; }
	node *&ret = alp[c - 'a'];
	if(!ret){ ret = new node(c); }
	return ret;
}

void delnode(node *nd){
	queue<node*> q;
	q.push(nd);
	while(q.empty()){
		nd = q.front();
		q.pop();
		for(size_t i = 0; i < nd->to.size(); ++i){
			node *next = nd->to[i];
			if(!--next->refcnt){
				q.push(next);
			}
		}
		delete nd;
	}
}


void dfs(node *nd0, LL a0, LL b0){
	stack<state> stk;
	stk.push(state(0, nd0, a0, b0, 0));
	while(!stk.empty()){
		state &tp = stk.top();
		int &num = tp.stnum;
		node *&nd = tp.nd;
		LL &a = tp.a;
		LL &b = tp.b;
		size_t &cntr = tp.cntr;

		if(num == 0){
			if(a >= b){
				stk.pop();
				continue;
			}
			if(nd->ch){
				nd->len = 1;
				if(a == 0){
					ans += nd->ch;
				}
				stk.pop();
				continue;
			}
			if(nd->len >= 0 && nd->len <= a){
				stk.pop();
				continue;
			}

			nd->len = 0;
			num = 1;
		}
		else if(num == 1){
			if(cntr >= nd->to.size()){
				stk.pop();
				continue;
			}
			node *next = nd->to[cntr];
			
			while(next->to.size() == 1){
				node *tmp = next;
				nd->to[cntr] = next->to[0];
				next = next->to[0];

				if(--tmp->refcnt){
					++next->refcnt;
				}
				else{
					delete tmp;
				}
			}

			num = 2;
			stk.push(state(0, next, a, b, 0));
		}
		else if(num == 2){
			node *next = nd->to[cntr];
			LL olen = next->len;
			a = max(a - olen, 0LL);
			b = max(b - olen, 0LL);
			nd->len = min(nd->len + olen, inf);

			if(next->len == 0){
				nd->to.erase(nd->to.begin() + cntr);
				--cntr;
				if(!--next->refcnt){
					delnode(next);
				}
			}
			
			++cntr;
			num = 1;
		}
	}
}

int main(){
	ios::sync_with_stdio(false);

	string s;
	LL q, a, b;
	char c;
	cin >> s >> q >> a >> b;
	--a;

	node *root = new node(0);
	root->to.resize(s.size());
	for(size_t i = 0; i < s.size(); ++i){
		node *next = getnode(s[i]);
		root->to[i] = next;
		++next->refcnt;
	}

	for(LL i = 0; i < q; ++i){
		cin >> c >> s;
		node *nd = alp[c - 'a'];
		if(!nd){ continue; }
		alp[c - 'a'] = 0;

		nd->ch = 0;
		nd->to.resize(s.size());
		for(size_t j = 0; j < s.size(); ++j){
			node *next = getnode(s[j]);
			nd->to[j] = next;
			++next->refcnt;
		}
	}

	dfs(root, a, b);
	if(ans.size() < b - a){
		ans = ".";
	}
	cout << ans << '\n';
	
	delnode(root);
}
accuracy: 1
time_ms: 190
memory_kb: 60352
final_rank: 2

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <climits>
#include <algorithm>
#include <cctype>
#include <cstdlib>
using namespace std;

typedef long long LL;

const LL inf = LLONG_MAX / 2;

struct node{
	char ch;
	LL refcnt;
	LL len;
	vector<node*> to;
	
	node(char c, LL r = 0, LL len = -1)
	: ch(c), refcnt(r), len(len) {}
};

struct state{
	int stnum;
	node *nd;
	LL a, b;
	size_t cntr;
	
	state(int s, node *nd, LL a, LL b, size_t c)
	: stnum(s), nd(nd), a(a), b(b), cntr(c) {}
};

node *alp[26];
node emp(0, inf, 0);
string ans;

node *getnode(int c){
	if(c == '.'){ return &emp; }
	node *&ret = alp[c - 'a'];
	if(!ret){ ret = new node(c); }
	return ret;
}

void delnode(node *nd){
	queue<node*> q;
	q.push(nd);
	while(q.empty()){
		nd = q.front();
		q.pop();
		for(size_t i = 0; i < nd->to.size(); ++i){
			node *next = nd->to[i];
			if(!--next->refcnt){
				q.push(next);
			}
		}
		delete nd;
	}
}


void dfs(node *nd0, LL a0, LL b0){
	stack<state> stk;
	stk.push(state(0, nd0, a0, b0, 0));
	while(!stk.empty()){
		state &tp = stk.top();
		int &num = tp.stnum;
		node *&nd = tp.nd;
		LL &a = tp.a;
		LL &b = tp.b;
		size_t &cntr = tp.cntr;

		if(num == 0){
			if(a >= b){
				stk.pop();
				continue;
			}
			if(nd->ch){
				nd->len = 1;
				if(a == 0){
					ans += nd->ch;
				}
				stk.pop();
				continue;
			}
			if(nd->len >= 0 && nd->len <= a){
				stk.pop();
				continue;
			}

			nd->len = 0;
			num = 1;
		}
		else if(num == 1){
			if(cntr >= nd->to.size()){
				stk.pop();
				continue;
			}
			node *next = nd->to[cntr];
			
			while(next->to.size() == 1){
				node *tmp = next;
				nd->to[cntr] = next->to[0];
				next = next->to[0];

				if(--tmp->refcnt){
					++next->refcnt;
					break;
				}

				delete tmp;
			}

			num = 2;
			stk.push(state(0, next, a, b, 0));
		}
		else if(num == 2){
			node *next = nd->to[cntr];
			LL olen = next->len;
			a = max(a - olen, 0LL);
			b = max(b - olen, 0LL);
			nd->len = min(nd->len + olen, inf);

			if(next->len == 0){
				nd->to.erase(nd->to.begin() + cntr);
				--cntr;
				if(!--next->refcnt){
					delnode(next);
				}
			}
			
			++cntr;
			num = 1;
		}
	}
}

int main(){
	ios::sync_with_stdio(false);

	string s;
	LL q, a, b;
	char c;
	cin >> s >> q >> a >> b;
	--a;

	node *root = new node(0);
	root->to.resize(s.size());
	for(size_t i = 0; i < s.size(); ++i){
		node *next = getnode(s[i]);
		root->to[i] = next;
		++next->refcnt;
	}

	for(LL i = 0; i < q; ++i){
		cin >> c >> s;
		node *nd = alp[c - 'a'];
		if(!nd){ continue; }
		alp[c - 'a'] = 0;

		nd->ch = 0;
		nd->to.resize(s.size());
		for(size_t j = 0; j < s.size(); ++j){
			node *next = getnode(s[j]);
			nd->to[j] = next;
			++next->refcnt;
		}
	}

	dfs(root, a, b);
	if(ans.size() < b - a){
		ans = ".";
	}
	cout << ans << '\n';
	
	delnode(root);
}
accuracy: 1
time_ms: 190
memory_kb: 60352
final_rank: 2

code_snippet: #include<stack>
#include<cstdio>
#include<cstring>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

typedef long long ll;

const ll INF=1LL<<61;

const int Q_MAX=300000;

int q;
ll a,b;

char from[Q_MAX+1],to[Q_MAX+1][16];

// dp[c][dep] := ( 文字 c からはじめて, クエリ dep, dep+1, ..., q-1 を順に処理したときにできる文字列の長さ )
ll dp[26][Q_MAX];
ll dfs_count(char c,int dep){
	if(dep==q) return 1;

	ll &res=dp[c-'a'][dep];
	if(res!=-1) return res;

	if(from[dep]==c){
		res=0;
		for(int i=0;to[dep][i];i++){
			res+=dfs_count(to[dep][i],dep+1);
			res=min(res,INF);
		}
	}
	else{
		res=dfs_count(c,dep+1);
	}
	return res;
}

struct state{
	int pos;
	char c;
	int dep;
};

int main(){
	char s[16];
	scanf("%s%d%lld%lld",s,&q,&a,&b);
	a--;
	rep(i,q){
		scanf(" %c%s",from+i,to[i]);
		if(to[i][0]=='.') to[i][0]='\0';
	}

	memset(dp,-1,sizeof dp);
	// 再帰が深くならないように適当に間引いて計算しておく
	for(char c='a';c<='z';c++) for(int dep=q-1;dep>=0;dep-=100) dfs_count(c,dep);

	// 経路圧縮用
	static char next_c[26][Q_MAX+1];
	static int next_dep[26][Q_MAX+1];
	// next_c, next_dep を初期化
	for(char c='a';c<='z';c++) rep(dep,q+1) {
		char &c2=next_c[c-'a'][dep];
		int &dep2=next_dep[c-'a'][dep];
		if(dep==q){
			c2=c;
			dep2=dep;
		}
		else{
			if(from[dep]==c){
				int len=strlen(to[dep]);
				int cnt=0,i0=-1;
				rep(i,len) if(dfs_count(to[dep][i],dep+1)>0) cnt++, i0=i;

				if(cnt!=1){
					c2=c;
					dep2=dep;
				}
				else{
					c2=to[dep][i0];
					dep2=dep+1;
				}
			}
			else{
				c2=c;
				dep2=dep+1;
			}
		}
	}

	int sz=0;
	static char ans[100010];

	ll cnt=0;
	stack<state> S;
	for(int i=strlen(s)-1;i>=0;i--){
		S.push((state){0,s[i],0});
	}
	while(!S.empty()){
		int pos=S.top().pos;
		char c=S.top().c;
		int dep=S.top().dep; S.pop();

		if(pos==0){
			if(sz==b-a) continue;

			if(a<=cnt && dep==q) ans[sz++]=c;

			ll num=dfs_count(c,dep);
			if(cnt+num<=a){
				cnt+=num;
			}
			else{
				char c2=next_c[c-'a'][dep];
				int dep2=next_dep[c-'a'][dep];
				// 経路圧縮しない
				if(dep2==dep){
					int len=strlen(to[dep]);
					for(int i=len-1;i>=0;i--) if(dfs_count(to[dep][i],dep+1)>0) S.push((state){0,to[dep][i],dep+1});
				}
				// 経路圧縮する
				else{
					S.push((state){1,c,dep});
					S.push((state){0,c2,dep2});
				}
			}
		}
		else{ // pos==1
			char c2=next_c[c-'a'][dep];
			int dep2=next_dep[c-'a'][dep];
			next_c[c-'a'][dep]=next_c[c2-'a'][dep2];
			next_dep[c-'a'][dep]=next_dep[c2-'a'][dep2];
		}
	}

	if(sz<b-a) puts(".");
	else       puts(ans);

	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 108660
final_rank: 4

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
#include <functional>
using namespace std;

const long long INF = LLONG_MAX / 4;

int q;
vector<string> s(1);
vector<vector<int> > to;
vector<long long> len;

void solve(long long a, long long b)
{
    stack<pair<int, int> > stk;
    stk.push(make_pair(0, 0));

    for(;;){
        int i = stk.top().first;
        int j = stk.top().second;
        stk.pop();

        while(j < (int)s[i].size()){
            int next = to[i][s[i][j]-'a'];
            if(next == -1){
                if(a <= 0)
                    cout << s[i][j];
                -- a;
                -- b;
            }else{
                if(a < len[next]){
                    stk.push(make_pair(i, j+1));
                    stk.push(make_pair(next, 0));
                    break;
                }else{
                    a -= len[next];
                    b -= len[next];
                }
            }
            if(b < 0){
                cout << endl;
                return;
            }
            ++ j;
        }
    }
}

int main()
{
    long long a, b;
    cin >> s[0] >> q >> a >> b;

    ++ q;
    s.resize(q);
    vector<char> c(q);
    for(int i=1; i<q; ++i){
        cin >> c[i] >> s[i];
        if(s[i] == ".")
            s[i] = "";
    }

    to.assign(q, vector<int>(26, -1));
    len.resize(q, 0);
    for(int i=q-1; i>=0; --i){
        for(unsigned j=0; j<s[i].size(); ++j){
            int next = to[i][s[i][j]-'a'];
            if(next == -1){
                ++ len[i];
            }else if(len[next] > 0){
                len[i] += len[next];
            }else{
                s[i].erase(s[i].begin() + j);
                -- j;
            }
            len[i] = min(len[i], INF);
        }

        if(i > 0){
            to[i-1] = to[i];
            if(s[i].size() == 1 && to[i][s[i][0]-'a'] != -1)
                to[i-1][c[i]-'a'] = to[i][s[i][0]-'a'];
            else
                to[i-1][c[i]-'a'] = i;
        }
    }

    if(b > len[0])
        cout << "." << endl;
    else
        solve(a-1, b-1);

    return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 65420
final_rank: 5

code_snippet: #include <iostream>
#include <map>
#include <cstring>
#include <vector>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

string S;
long long Q,A,B;

struct NODE{
	char c;
	vector<NODE*> ch;
};
#define INF (1e18+10000)

NODE* alp[128] = {};

map<NODE*,long long> memo;

long long add(long long a,long long b){
	return (long double)a+b >= INF ? INF : a+b; 
}
long long size(NODE *r){
	if( r->c != '.' ) return 1;
	if( memo.count(r) ) return memo[r];
	memo[r] = 0;
	for(int i = 0 ; i < r->ch.size() ; i++){
		memo[r] = add(memo[r],size(r->ch[i]));
	}
	return memo[r];
}

int C = 0;
int F = 0;
int dfs(NODE *r,long long cur){
	if( C == 0 && F == 1 ) return 0;
	if( r->c != '.' ){
		if( cur == 0 && F == 0 ){
			F = 1;
			cout << r->c;
			C = B-A;
		}else if( F ){
			if( C > 0 ){
				C--;
				cout << r->c;
			}
		}
	}
	for(int i = 0 ; i < r->ch.size() ; i++){
		if( F ){
			dfs(r->ch[i],cur);
		}else{
			if( size(r->ch[i]) <= cur ){
				cur -= size(r->ch[i]);
			}else{
				dfs(r->ch[i],cur);
			}
		}
	}
	
	
}

int main(){
	for(int i = 'a' ; i <= 'z' ; i++){
		alp[i] = new NODE();
		alp[i]->c = i;
	}
	NODE* root = new NODE();
	root->c = '.';
	cin >> S;
	for(int i = 0 ; i < S.size() ; i++){
		root->ch.push_back(alp[S[i]]);
	}
	cin >> Q >> A >> B;
	A--,B--;
	for(int i = 0 ; i < Q ; i++){
		char x;
		string y;
		cin >> x >> y;
		NODE *prev = alp[x];
		prev->c = '.';
		
		alp[x] = new NODE();
		alp[x]->c = x;
		
		if( y != "." ){
			for(int j = 0 ; j < y.size() ; j++){
				prev->ch.push_back(alp[y[j]]);
			}
		}
	}
	if( size(root) <= B ){
		cout << "." << endl;
		return 0;
	}
	dfs(root,A);
	cout << endl;
}
accuracy: 0.07142857142857142
time_ms: 10
memory_kb: 1864
final_rank: 7

code_snippet: #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long int64;

const int ALPHABET_SIZE = 26;
const int MAX_Q = int(3e5 + 10);
const int MAX_L = int(1e5 + 10);
const int MAX_P = 10;
const int64 INF = int64(2e18 + 10);

int Q;
int64 A, B;
char S[MAX_P + 1];

struct Node {
	int64 size;
	char isChar;
	Node *alter;
	Node *childs[MAX_P + 1];
	Node():size(-1), isChar(0), alter(0)
	{
		memset(childs, 0, sizeof(childs));
	}
};

Node *nodes[ALPHABET_SIZE + 1];

void init() {
	scanf("%s ", S);
	scanf("%d%lld%lld ", &Q, &A, &B);
	--A;
	for (int i = 0; i <= ALPHABET_SIZE; ++i) {
		nodes[i] = new Node();
	}
	for (int i = 0; S[i]; ++i) {
		nodes[ALPHABET_SIZE]->childs[i] = nodes[int(S[i] - 'a')];
	}
}

inline void normalize(int64 &x) {
	if (x > INF) {
		x = INF;
	}
}

void proc() {
	char ch, pat[MAX_P + 1];
	scanf(" %c %s ", &ch, pat);
	Node *old = nodes[int(ch - 'a')];
	nodes[int(ch - 'a')] = new Node();
	if (pat[0] == '.') {
		old->size = 0;
		old->alter = old;
	}
	else {
		for (int i = 0; pat[i]; ++i) {
			old->childs[i] = nodes[int(pat[i] - 'a')];
		}
	}
}

struct State {
	Node *node;
	int index;
	int64 from, to;

	State(){}
	State(Node *node_, int index_, int64 from_ = -1, int64 to_ = -1):
		node(node_), index(index_), from(from_), to(to_)
	{}
};

void traverse(Node *nd) {
	static State stack[MAX_Q + 10];
	int st = 0;
	stack[st++] = State(nd, 0);
	for (;st>0;) {
		State s = stack[--st];
		nd = s.node;
		int idx = s.index;
		if (idx == 0) {
			nd->size = 0;
			nd->alter = nd;
			if (nd->isChar) {
				nd->size = 1;
				continue;
			}
		}

		for (;nd->childs[idx]; ++idx) {
			if (nd->childs[idx]->size == -1) {
				stack[st++] = State(nd, idx+1);
				stack[st++] = State(nd->childs[idx], 0);
				break;
			}
		}
		if (!nd->childs[idx]) {
			for (int i = 0; nd->childs[i]; ++i) {
				normalize(nd->size += nd->childs[i]->size);
			}
			if (nd->size == 0) {
				continue;
			}
			int p = 0;
			for (int i = 0; nd->childs[i]; ++i) if (nd->childs[i]->size > 0) {
				nd->childs[p] = nd->childs[i]->alter;
				++p;
			}
			nd->childs[p] = 0;
			if (nd->size == nd->childs[0]->size) {
				nd->alter = nd->childs[0];
			}
		}
	}
}

void print(Node *nd, int64 from, int64 to) {
	static State stack[MAX_Q + 10];
	int st = 0;
	stack[st++] = State(nd, 0, from, to);
	for (;st>0;) {
		State s = stack[--st];
		nd = s.node;
		int idx = s.index;
		from = s.from;
		to = s.to;

		const int64 len = to - from;
		if (len <= 0) {
			continue;
		}
		if (nd->isChar) {
			putchar(nd->isChar);
			continue;
		}

		for (; nd->childs[idx] && from < to; ++idx) {
			int64 sz = nd->childs[idx]->size;
			if (sz <= from) {
				from -= sz;
				to -= sz;
			}
			else {
				stack[st++] = State(nd, idx+1, 0, to - sz);
				stack[st++] = State(nd->childs[idx], 0, from, min(sz, to));
				break;
			}
		}
	}
}

void solve() {
	for (int _ = 0; _ < Q; ++_) {
		proc();
	}
	for (int i = 0; i < ALPHABET_SIZE; ++i) {
		nodes[i]->isChar = i + 'a';
	}
	traverse(nodes[ALPHABET_SIZE]);
	if (nodes[ALPHABET_SIZE]->size < B) {
		puts(".");
	}
	else {
		print(nodes[ALPHABET_SIZE], A, B);
		puts("");
	}
}

int main() {
	init();
	solve();
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 50800
final_rank: 1