#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 6e5 + 5;
struct SegmentTree {
int sz;
vector<int> val;
int ide = 0x3f3f3f3f;
SegmentTree(){}
SegmentTree(int n) {
for (sz = 1; sz < n; sz *= 2);
val.assign(2 * sz, ide);
}
void pushup(int x) {
val[x] = min(val[x * 2], val[x * 2 + 1]);
}
void mdf(int x, int lx, int rx, int p, int v) {
if (lx + 1 == rx) {
val[x] = v;
return ;
}
int m = (lx + rx) / 2;
if (p < m)
mdf(x * 2, lx, m, p, v);
else
mdf(x * 2 + 1, m, rx, p, v);
pushup(x);
}
int qry(int x, int lx, int rx, int l, int r) {
if (l <= lx && rx <= r)
return val[x];
if (l >= rx || lx >= r)
return ide;
int m = (lx + rx) / 2;
return min(qry(x * 2, lx, m, l, r), qry(x * 2 + 1, m, rx, l, r));
}
} st;
ll n;
ll lst = 0, lstb = 0; //上一次的答案,上一次的border总和
map<ll, ll> mp; //mp[i]表示可疑度为i的border个数
char ch[N];
ll w[N];
ll nxt[N];
ll dif[N]; //dif[i]表示i在nxt树上第一个与它下一个字符对应不同的
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
cin >> n;
st = SegmentTree(n);
nxt[0] = 0;
dif[0] = 0;
int MMM = (1 << 30) - 1;
for (int i = 1; i <= n; i++) {
ll now = lstb;
while (true) {
ch[i] = getchar();
if (ch[i] != ' ' && ch[i] != '\n')
break;
}
scanf("%lld", &w[i]);
ch[i] = (lst + ch[i] - 'a') % 26 + 'a';
w[i] = w[i] ^ (lst & MMM);
// printf("\"%c, %d\"\n", ch[i], w[i]);
st.mdf(1, 1, st.sz + 1, i, w[i]);
// cout << "w[2,3]=" << st.qry(1, 1, st.sz + 1, 2, 4) << endl;
if (i > 1) {
int cur = nxt[i - 1];
while (cur > 0 && ch[cur + 1] != ch[i])
cur = nxt[cur];
if (ch[cur + 1] == ch[i])
nxt[i] = cur + 1;
}
// cout << nxt[i] << endl;
//更新dif[nxt[i]]
if (ch[nxt[i] + 1] == ch[nxt[nxt[i]] + 1])
dif[nxt[i]] = dif[nxt[nxt[i]]];
else
dif[nxt[i]] = nxt[nxt[i]];
//1 删除
if (i > 1) {
// cout << "删除:\n";
int pos = nxt[i - 1];
while (true) {
if (pos == 0)
break;
if (ch[pos + 1] != ch[i]) {
int sus = st.qry(1, 1, st.sz + 1, i - pos, i);
mp[sus]--;
now -= sus;
// printf("[%d,%d):", i - pos, i);
// cout << ch[pos + 1] << ' ' << ch[i] << endl;
// cout << pos << ',' << sus << endl;
pos = nxt[pos];
}
else
pos = dif[pos];
}
}
//2 修改
if (mp.begin() != mp.end()) {
// cout << "修改:\n";
auto pt = mp.end();
pt--;
while (true) {
if ((*pt).first <= w[i])
break;
// printf("(%d,%d)\n", (*pt).first, (*pt).second);
now -= 1ll * (*pt).first * (*pt).second;
now += 1ll * (*pt).second * w[i];
mp[w[i]] += (*pt).second;
mp[(*pt).first] = 0;
if (pt == mp.begin())
break;
pt--;
}
}
//3 添加
if (ch[i] == ch[1]) {
// cout << "添加:\n";
mp[w[i]]++;
now += w[i];
// printf("add:%d\n", w[i]);
}
// cout << "答案:";
printf("%lld\n", now + lst);
lst += now;
lstb = now;
// for (auto i: mp)
// printf("(%d,%d)", i.first, i.second);
// cout << endl;
// cout << endl;
}
return 0;
}
/*
4
s 838220732
e 269827753
h 1020606579
s 812800242
*/