Problem:
Substring
長さnの文字列s=s
1
,s
2
,…,s
n
およびm個のクエリが与えられる。
各クエリq
k
(1 ≤ k ≤ m)は、"L++", "L--", "R++", "R--"の4種類のいずれかであり、
k番目のクエリq
k
に対してl[k]とr[k]を以下で定義する。
L++：l[k]=l[k-1]+1,r[k]=r[k-1]
L--：l[k]=l[k-1]-1,r[k]=r[k-1]
R++：l[k]=l[k-1],r[k]=r[k-1]+1
R--：l[k]=l[k-1],r[k]=r[k-1]-1
但し、l[0]=r[0]=1である。
この時、m個の部分文字列
s
l[k]
, s
l[k]+1
, …, s
r[k]-1
, s
r[k]
(1 ≤ k ≤ m)
について、何種類の文字列が作られるかを答えよ。
Input
入力は以下の形式で与えられる
n m
s
q
1
q
2
…
q
m
Constraints
文字列sは小文字アルファベットからなる
1 ≤ n ≤ 3×10
5
1 ≤ m ≤ 3×10
5
q
k
(1 ≤ k ≤ m)は、"L++"、"L--"、"R++"、"R--"のいずれか
1 ≤ l[k] ≤ r[k] ≤ n (1 ≤ k ≤ m)
Output
問題の解を1行に出力せよ
Sample Input 1
5 4
abcde
R++
R++
L++
L--
Output for the Sample Input 1
3
l[1]=1, r[1]=2であり、部分文字列は"ab"である
l[2]=1, r[2]=3であり、部分文字列は"abc"である
l[3]=2, r[3]=3であり、部分文字列は"bc"である
l[4]=1, r[4]=3であり、部分文字列は"abc"である
よって、生成される文字列は{"ab","abc","bc"}の3種類である。
Sample Input 2
4 6
abab
R++
L++
R++
L++
R++
L++
Output for the Sample Input 2
4
l[1]=1, r[1]=2であり、部分文字列は"ab"である
l[2]=2, r[2]=2であり、部分文字列は"b"である
l[3]=2, r[3]=3であり、部分文字列は"ba"である
l[4]=3, r[4]=3であり、部分文字列は"a"である
l[5]=3, r[5]=4であり、部分文字列は"ab"である
l[6]=4, r[6]=4であり、部分文字列は"b"である
よって、生成される文字列は{"a","ab","b","ba"}の4種類である。
Sample Input 3
10 13
aacacbabac
R++
R++
L++
R++
R++
L++
L++
R++
R++
L--
L--
R--
R--
Output for the Sample Input 3
11

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


// https://ei1333.github.io/luzhiled/snippets/other/random-number-generator.html
struct rand_gen{
  mt19937 mt;
  rand_gen() : mt(chrono::steady_clock::now().time_since_epoch().count()) {}
  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution< int > dist(a, b - 1);
    return dist(mt);
  }
  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};
/*
  rand_gen rnd;
  cout << rnd(10,100) << "\n";
*/


long long modinv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m; 
    if (u < 0) u += m;
    return u;
}

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m;cin >> n >> m;
  string s;cin >> s;
  set<pll> st;
  int l = 0,r = 1;
  rand_gen rnd;
  ll base = rnd(10,MOD);
  ll hsh = s[0];
  ll inv = modinv(base,MOD);
  vector<ll> pw(sz(s),1);
  rep(i,0,sz(s)-1)pw[i+1] = pw[i]*base%MOD;
  rep(_,0,m){
    string SS;cin >> SS;
    if(SS == "L++"){
      hsh = (hsh-s[l++]+MOD)*inv%MOD;
    }else if(SS == "L--"){
      hsh = (hsh*base%MOD + s[--l])%MOD;
    }else if(SS == "R++"){
      hsh = (hsh + s[r++]*pw[r-l-1]%MOD)%MOD;
    }else if(SS == "R--"){
      hsh = (hsh - s[--r]*pw[r-l]%MOD + MOD)%MOD;
    }
    st.insert({hsh,r-l});
  }
  cout << sz(st) << endl;
  

  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 24468
final_rank: 8

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
#define MOD 1000000007
// #define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


// https://ei1333.github.io/luzhiled/snippets/other/random-number-generator.html
struct rand_gen{
  mt19937 mt;
  rand_gen() : mt(chrono::steady_clock::now().time_since_epoch().count()) {}
  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution< int > dist(a, b - 1);
    return dist(mt);
  }
  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};
/*
  rand_gen rnd;
  cout << rnd(10,100) << "\n";
*/


long long modinv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m; 
    if (u < 0) u += m;
    return u;
}

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m;cin >> n >> m;
  string s;cin >> s;
  set<ll> st;
  int l = 0,r = 1;
  rand_gen rnd;
  ll base = rnd(10,MOD);
  ll hsh = s[0];
  ll inv = modinv(base,MOD);
  vector<ll> pw(sz(s),1);
  rep(i,0,sz(s)-1)pw[i+1] = pw[i]*base%MOD;
  rep(_,0,m){
    string SS;cin >> SS;
    if(SS == "L++"){
      hsh = (hsh-s[l++]+MOD)*inv%MOD;
    }else if(SS == "L--"){
      hsh = (hsh*base%MOD + s[--l])%MOD;
    }else if(SS == "R++"){
      hsh = (hsh + s[r++]*pw[r-l-1]%MOD)%MOD;
    }else if(SS == "R--"){
      hsh = (hsh - s[--r]*pw[r-l]%MOD + MOD)%MOD;
    }
    st.insert(hsh);
  }
  cout << sz(st) << endl;
  

  return 0;
}
accuracy: 0.07692307692307693
time_ms: 90
memory_kb: 19648
final_rank: 19

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


// https://ei1333.github.io/luzhiled/snippets/other/random-number-generator.html
struct rand_gen{
  mt19937 mt;
  rand_gen() : mt(chrono::steady_clock::now().time_since_epoch().count()) {}
  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution< int > dist(a, b - 1);
    return dist(mt);
  }
  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};
/*
  rand_gen rnd;
  cout << rnd(10,100) << "\n";
*/


long long modinv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m; 
    if (u < 0) u += m;
    return u;
}

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m;cin >> n >> m;
  string s;cin >> s;
  set<ll> st;
  int l = 0,r = 1;
  rand_gen rnd;
  ll base = rnd(10,MOD);
  ll hsh = s[0];
  ll inv = modinv(base,MOD);
  vector<ll> pw(sz(s),1);
  rep(i,0,sz(s)-1)pw[i+1] = pw[i]*base%MOD;
  rep(_,0,m){
    string SS;cin >> SS;
    if(SS == "L++"){
      hsh = (hsh-s[l++]+MOD)*inv%MOD;
    }else if(SS == "L--"){
      hsh = (hsh*base%MOD + s[--l])%MOD;
    }else if(SS == "R++"){
      hsh = (hsh + s[r++]*pw[r-l-1]%MOD)%MOD;
    }else if(SS == "R--"){
      hsh = (hsh - s[--r]*pw[r-l]%MOD + MOD)%MOD;
    }
    st.insert(hsh);
  }
  cout << sz(st) << endl;
  

  return 0;
}
accuracy: 0.07692307692307693
time_ms: 90
memory_kb: 19600
final_rank: 18

code_snippet: #include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

template<typename T> T inf;
template<> constexpr int inf<int> = 1e9;
template<> constexpr ll inf<ll> = 1e18;
template<> constexpr ld inf<ld> = 1e30;

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

class RollingHash {
  const int n;
  static const ll moda = 1000000000000037LL;
  static const ll modb = 1000000000000091LL;
  static const ll pa = 17LL;
  static const ll pb = 19LL;
  vector<ll> a, b, p, q;
public:
  RollingHash (const string &str) :
    n(str.size()), a(n+1, 0), b(n+1, 0), p(n+1, 1), q(n+1, 1) {
    REP(i,n) a[i+1] = (a[i] * pa + str[i]) % moda;
    REP(i,n) b[i+1] = (b[i] * pb + str[i]) % modb;
    REP(i,n) p[i+1] = p[i] * pa % moda;
    REP(i,n) q[i+1] = q[i] * pb % modb;
  }
  pair<ll,ll> query(int l, int r) {
    return make_pair(((__int128)p[r - l] * a[l] - a[r] + moda) % moda,
                     ((__int128)q[r - l] * b[l] - b[r] + modb) % modb);
  }
};

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha;
  cout.imbue(loc);

  int n, m;
  cin >> n >> m;
  string s;
  cin >> s;
  RollingHash rh(s);
  set<pair<ll,ll>> h;
  int l = 0, r = 1;
  REP(i,m) {
    string q;
    cin >> q;
    *(q[0] == 'L' ? &l : &r) += (q[1] == '+' ? 1 : -1);
    h.insert(rh.query(l, r));
  }
  cout << h.size() << endl;
  return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 31564
final_rank: 14

code_snippet: #include <iostream>
#include <string>
#include <set>
using namespace std;

const unsigned long long BASE = 100000000003;
unsigned long long power[300005];
int main()
{
    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;
    int l = 0, r = 0;

    power[0] = 1;
    for (int i = 0; i < n; ++i)
    {
        power[i + 1] = (power[i] * BASE);
    }

    set<unsigned long long> unique_hashes;

    unsigned long long hash_value = s[0];

    for (int i = 0; i < m; ++i)
    {
        string query;
        cin >> query;

        if (query == "L++")
        {
            hash_value = (hash_value  - s[l] * power[r - l] );
            l++;
        }
        else if (query == "L--")
        {
            l--;
            hash_value = (hash_value + s[l] * power[r - l]);
        }
        else if (query == "R++")
        {
            r++;
            hash_value = (hash_value * BASE + s[r]);
        }
        else if (query == "R--")
        {
            hash_value = ((hash_value - s[r])* 18245175647506858667ULL);
            r--;
        }

        unique_hashes.insert(hash_value);
    }

    cout << unique_hashes.size() << endl;

    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 19608
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

namespace Random {
mt19937_64 randgen(chrono::steady_clock::now().time_since_epoch().count());
using u64 = unsigned long long;
u64 get() {
    return randgen();
}
template <typename T> T get(T L) { // [0,L]

    return get() % (L + 1);
}
template <typename T> T get(T L, T R) { // [L,R]

    return get(R - L) + L;
}
double uniform() {
    return double(get(1000000000)) / 1000000000;
}
string str(int n) {
    string ret;
    rep(i, 0, n) ret += get('a', 'z');
    return ret;
}
template <typename Iter> void shuffle(Iter first, Iter last) {
    if (first == last)
        return;
    int len = 1;
    for (auto it = first + 1; it != last; it++) {
        len++;
        int j = get(0, len - 1);
        if (j != len - 1)
            iter_swap(it, first + j);
    }
}
template <typename T> vector<T> select(int n, T L, T R) { // [L,R]

    if (n * 2 >= R - L + 1) {
        vector<T> ret(R - L + 1);
        iota(ALL(ret), L);
        shuffle(ALL(ret));
        ret.resize(n);
        return ret;
    } else {
        unordered_set<T> used;
        vector<T> ret;
        while (SZ(used) < n) {
            T x = get(L, R);
            if (!used.count(x)) {
                used.insert(x);
                ret.push_back(x);
            }
        }
        return ret;
    }
}

void relabel(int n, vector<pair<int, int>> &es) {
    shuffle(ALL(es));
    vector<int> ord(n);
    iota(ALL(ord), 0);
    shuffle(ALL(ord));
    for (auto &[u, v] : es)
        u = ord[u], v = ord[v];
}
template <bool directed, bool simple> vector<pair<int, int>> genGraph(int n) {
    vector<pair<int, int>> cand, es;
    rep(u, 0, n) rep(v, 0, n) {
        if (simple and u == v)
            continue;
        if (!directed and u > v)
            continue;
        cand.push_back({u, v});
    }
    int m = get(SZ(cand));
    vector<int> ord;
    if (simple)
        ord = select(m, 0, SZ(cand) - 1);
    else {
        rep(_, 0, m) ord.push_back(get(SZ(cand) - 1));
    }
    for (auto &i : ord)
        es.push_back(cand[i]);
    relabel(n, es);
    return es;
}
vector<pair<int, int>> genTree(int n) {
    vector<pair<int, int>> es;
    rep(i, 1, n) es.push_back({get(i - 1), i});
    relabel(n, es);
    return es;
}
}; // namespace Random


/**
 * @brief Random
 */

struct RollingHash {
    using ull = unsigned long long;
    const ull MOD = 0x1fffffffffffffff;
    const ull base;
    vector<ull> hashed, power;

    static constexpr ull mask(ll a) { return (1ULL << a) - 1; }

    inline ull mul(ull a, ull b) const {
        __uint128_t ans = __uint128_t(a) * b;
        ans = (ans >> 61) + (ans & MOD);
        if (ans >= MOD)
            ans -= MOD;
        return ans;
    }

    static inline ull genbase() { return Random::get(ull(0x1fffffffffffffff)); }
    RollingHash() = default;

    RollingHash(const string &s, ull base) : base(base) {
        ll n = s.size();
        hashed.assign(n + 1, 0);
        power.assign(n + 1, 0);
        power[0] = 1;
        for (ll i = 0; i < n; i++) {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = mul(hashed[i], base) + s[i];
            if (hashed[i + 1] >= MOD)
                hashed[i + 1] -= MOD;
        }
    }

    ull get(ll l, ll r) const {
        ull ret = hashed[r] + MOD - mul(hashed[l], power[r - l]);
        if (ret >= MOD)
            ret -= MOD;
        return ret;
    }

    ull connect(ull h1, ull h2, ll h2len) const {
        ull ret = mul(h1, power[h2len]) + h2;
        if (ret >= MOD)
            ret -= MOD;
        return ret;
    }

    void connect(const string &s) {
        ll n = hashed.size() - 1, m = s.size();
        hashed.resize(n + m + 1);
        power.resize(n + m + 1);
        for (ll i = n; i < n + m; i++) {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = mul(hashed[i], base) + s[i - n];
            if (hashed[i + 1] >= MOD)
                hashed[i + 1] -= MOD;
        }
    }

    ll LCP(const RollingHash &b, ll l1, ll r1, ll l2, ll r2) {
        ll len = min(r1 - l1, r2 - l2);
        ll low = -1, high = len + 1;
        while (high - low > 1) {
            ll mid = (low + high) / 2;
            if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
                low = mid;
            else
                high = mid;
        }
        return low;
    }
};

/**
 * @brief Rolling Hash
 */

int main() {
    int N, M;
    cin >> N >> M;
    string S;
    cin >> S;
    RollingHash Hash(S,RollingHash::genbase());
    set<ll> ANS;
    int L = 0, R = 1;
    rep(i,0,M) {
        string T;
        cin >> T;
        if (T == "L++") L++;
        if (T == "L--") L--;
        if (T == "R++") R++;
        if (T == "R--") R--;
        ANS.insert(Hash.get(L,R));
    }
    cout << ANS.size() << endl;
}
accuracy: 1
time_ms: 110
memory_kb: 22080
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define int long long
using namespace std;

const int MAX_N = 3e5 + 10;

set<pair<int,long long> > st;
long long p[MAX_N];
long long pr[MAX_N];
long long key = 71;
int md = 1e9 + 7;

//int
main(){

    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;

    p[0] = key;
    for(int i = 1; i <= n; ++i){
        p[i] = p[i - 1] * key % md;
    }

    for(int i = 1; i <= n; ++i){
        pr[i] = (pr[i - 1] + (int)(s[i - 1] - 'a' + 1) * 1ll * p[i - 1] % md) % md;
    }

    int l = 1, r = 1;
    for(int i = 1; i <= m; ++i){
        string t;
        cin >> t;
        if(t == "L++") ++l; else
        if(t == "L--") --l; else
        if(t == "R++") ++r; else --r;
       st.insert({r - l + 1,(pr[r] - pr[l - 1] + md) % md * p[n - r] % md});
    }

    cout << st.size() << endl;


}
accuracy: 1
time_ms: 180
memory_kb: 26560
final_rank: 15

code_snippet: #include<bits/stdc++.h>
#define int long long
using namespace std;

const int MAX_N = 3e5 + 10;

set<long long> st;
long long p[MAX_N];
long long pr[MAX_N];
long long key = 71;
int md = 1e9 + 7;

//int
main(){

    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;

    p[0] = key;
    for(int i = 1; i <= n; ++i){
        p[i] = p[i - 1] * key % md;
    }

    for(int i = 1; i <= n; ++i){
        pr[i] = (pr[i - 1] + (int)(s[i - 1] - 'a' + 1) * 1ll * p[i - 1] % md) % md;
    }

    int l = 1, r = 1;
    for(int i = 1; i <= m; ++i){
        string t;
        cin >> t;
        if(t == "L++") ++l; else
        if(t == "L--") --l; else
        if(t == "R++") ++r; else --r;
       st.insert((pr[r] - pr[l - 1] + md) % md * p[n - r] % md);
    }

    cout << st.size() << endl;


}
accuracy: 0.07692307692307693
time_ms: 200
memory_kb: 21832
final_rank: 20

code_snippet: // competitive-verifier: PROBLEM
#include <cassert>
#include <cstdint>
#include <limits>
#include <random>
#include <string>
#include <vector>
/**
 * @brief ローリングハッシュ
 * @see https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
 * @see https://yosupo.hatenablog.com/entry/2023/08/06/181942
 */
struct rolling_hash {
    rolling_hash() : _size(), base((std::uint64_t)std::random_device()() + 2), data(), p() {}
    rolling_hash(const std::string &_s, uint64_t base = (std::uint64_t)std::random_device()() + 2)
        : _size(_s.size()), base(base), data(1), p(1, 1) {
        std::uint64_t x = 0, t = 1, y;
        for (const auto c : _s) {
            x = _mul(x, base) + c;
            x = (__builtin_usubl_overflow(x, mod, &y) ? x : y);
            data.emplace_back(x);
            t = _mul(t, base);
            p.emplace_back(t);
        }
    }
    std::uint64_t get_base() const { return base; }
    /// get hash of s[0...r]
    std::uint64_t get(int r) const { return data[r]; }
    /// get hash of s[l...r]
    std::uint64_t get(int l, int r) const {
        assert(0 <= l && l <= r && r <= _size);
        std::uint64_t x = data[r] + mod - _mul(data[l], p[r - l]), y;
        return __builtin_usubl_overflow(x, mod, &y) ? x : y;
    }
    /// get hash of s.substr(pos, len)
    std::uint64_t substr(int pos, int len = std::numeric_limits<int>::max()) const {
        assert(0 <= pos && pos <= _size);
        len = std::min(len, _size - pos);
        std::uint64_t x = data[pos + len] + mod - _mul(data[pos], p[len]), y;
        return __builtin_usubl_overflow(x, mod, &y) ? x : y;
    }
    /// search string
    std::vector<int> search(const std::string &s) {
        std::vector<int> res;
        int n = s.size();
        if (n > _size) return res;
        std::uint64_t x = 0, y;
        for (char c : s) {
            x = _mul(x, base) + c;
            x = (__builtin_usubl_overflow(x, mod, &y) ? x : y);
        }
        for (int i = 0; i <= _size - n; ++i) {
            if (get(i, i + n) == x) res.emplace_back(i);
        }
        return res;
    }
    std::uint64_t hash(const std::string &s) const {
        std::uint64_t x = 0, y;
        for (const auto c : s) {
            x = _mul(x, base) + c;
            x = (__builtin_usubl_overflow(x, mod, &y) ? x : y);
        }
        return x;
    }
  private:
    static constexpr std::uint64_t mod = (1ul << 61) - 1;
    int _size;
    std::uint64_t base;
    std::vector<std::uint64_t> data, p;
    constexpr std::uint64_t _mul(std::uint64_t a, std::uint64_t b) const {
        __uint128_t t = (__uint128_t)a * b;
        a = (t >> 61) + (t & mod);
        return __builtin_usubl_overflow(a, mod, &b) ? a : b;
    }
    constexpr std::uint64_t _pow(std::uint64_t x, std::uint64_t k) const {
        std::uint64_t res = 1;
        for (; k; k >>= 1) {
            if (k & 1) res = _mul(res, x);
            x = _mul(x, x);
        }
        return res;
    }
};
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
int main(void) {
    int n, q;
    cin >> n >> q;
    string s;
    cin >> s;
    rolling_hash rh(s);
    int l = 0, r = 1;
    unordered_set<uint64_t> st;
    while (q--) {
        string t;
        cin >> t;
        if (t == "L++") {
            ++l;
        } else if (t == "L--") {
            --l;
        } else if (t == "R++") {
            ++r;
        } else {
            --r;
        }
        st.emplace(rh.get(l, r));
    }
    co(st.size());
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 22192
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

// Reference: https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
#define ull unsigned long long 
// ハッシュの計算用
constexpr ull MASK30 = (1LL<<30)-1;
constexpr ull MASK31 = (1LL<<31)-1;
constexpr ull MOD = (1LL<<61)-1;
constexpr ull MASK61 = MOD;
constexpr ull POSITIVIZER = MOD * ((1<<3)-1);

// mod 2^61-1 を計算する関数
ull calcMod(ull x){
    ull xu = x>>61;
    ull xd = x&MASK61;
    ull res = xu+xd;
    if(res >= MOD) res -= MOD;
    return res;
}

// a*b mod 2^61-1 を返す関数
ull mul(ull a, ull b){
    ull au = a>>31, ad = a&MASK31;
    ull bu = b>>31, bd = b&MASK31;
    ull mid = ad*bu+au*bd;
    ull midu = mid>>30;
    ull midd = mid&MASK30;
    return au*bu*2+midu+(midd<<31)+ad*bd; // ハッシュの計算の時に mod をとった方が早くなる、
}

// a^b mod 2^61-1 を計算
ull modpow(ull a, ull b){
    ull res = 1;
    while(b > 0){
        if(b&1) res = calcMod(mul(res, a));
        a = calcMod(mul(a, a));
        b >>= 1;
    }
    return res;
}

// 基数を乱数を使って定める（ハック対策）
// Reference: https://trap.jp/post/1036/
ull randomized_base(ull r=37, ull max_s=127){
    ull k = rand()+max_s+1;
    while(gcd(MOD-1, k) != 1 || modpow(r, k) <= max_s){
        k = rand()+max_s+1;
    }
    return modpow(r, k);
}


template<typename Str>
class RollingHash {
    int n; // 文字列のサイズ
    ull base; // 基数 
    vector<ull> hash, powmemo; // ハッシュテーブルと基数の累乗のメモ


    // ハッシュテーブル構築
    void build(const Str &s){
        n = (int)s.size();
        hash.resize(n+1);
        powmemo.resize(n+1);
        powmemo[0] = 1;
        hash[0] = 0;
        for(int i = 0; i < n; i++){
            hash[i+1] = calcMod(mul(hash[i], base)+s[i]);
            powmemo[i+1] = calcMod(mul(powmemo[i], base));
        }
    }

public:
    RollingHash(const Str &s, ull _base=0){
        if(_base != 0) base = _base;
        else base = randomized_base();
        build(s);
    }
    
    // 開区間 [l, r) の hash 値を求める
    ull get(int l, int r = -1){
        if(r == -1) r = n;
        assert(l <= r);
        if(l == r) return 0LL;
        return calcMod(hash[r] + POSITIVIZER - mul(hash[l], powmemo[r-l]));
    }

    // hash a+b を求める（b の文字列としてのサイズが必要）
    ull unite(ull a, ull b, int bsize){
        return calcMod(mul(a, powmemo[bsize])+b);
    }

    // 開区間 [l1, r1) と ハッシュテーブル b の開区間 [l2, r2) における最長共通接頭辞
    int LCP(const RollingHash &b, int l1, int r1, int l2, int r2) {
        int len = min(r1 - l1, r2 - l2);
        int low = -1, high = len + 1;
        while(high - low > 1) {
            int mid = (low + high) / 2;
            if(get(l1, l1 + mid) == b.get(l2, l2 + mid)) low = mid;
            else high = mid;
        }
        return low;
    }
};

int main(){

    int n, m; cin >> n >> m;
    string s; cin >> s;
    RollingHash<string> table(s);
    set<ull> t;
    int l = 0, r = 1;
    rep(_, 0, m){
        string q; cin >> q;
        if(q == "L++"){
            l++;
        }else if(q == "L--"){
            l--;
        }else if(q == "R++"){
            r++;
        }else{
            r--;
        }
        t.insert(table.get(l, r));
    }
    cout << t.size() << endl;
    
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 22268
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
ll c=1e9+7;
int main(){
    int n, m, l=0, r=0;
    char s[300003], q[300003];
    ll hsh[300003], pw[300003];
    vector<ll> vec;
    scanf("%d %d %s", &n, &m, s);
    hsh[0] = s[0];
    pw[0] = 1;
    for(int i=1;i<300003;i++){
        hsh[i] = hsh[i-1]*c + s[i];
        pw[i] = pw[i-1]*c;
    }
    for(int i=0;i<m;i++){
        scanf("%s", q);
        if(q[0]=='L'){
            if(q[1]=='+') l++;
            else l--;
        } else{
            if(q[1]=='+') r++;
            else r--;
        }
        ll res = hsh[r];
        if(l>0) res -= hsh[l-1]*pw[r-l+1];
        vec.push_back(res);
    }
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    printf("%d\n", vec.size());
    return(0);
}
accuracy: 1
time_ms: 30
memory_kb: 12024
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

class RollingHash {
    public:
    static const uint64_t MASK30 = (1ull << 30) - 1;
    static const uint64_t MASK31 = (1ull << 31) - 1;
    static const uint64_t _MOD = (1ull << 61) - 1;
    static const uint64_t MASK61 = _MOD;
    static const uint64_t POSITIVIZER = _MOD * 4;
    const uint64_t base;
    vector<uint64_t> power;

    static uint64_t generateBase() {
        mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
        uniform_int_distribution<uint64_t> rand(1ull << 32, RollingHash::_MOD - 1);
        return rand(mt);
    }

    uint64_t Mul(uint64_t a, uint64_t b) {
        uint64_t au = a >> 31, ad = a & MASK31, bu = b >> 31, bd = b & MASK31;
        uint64_t mid = ad * bu + au * bd;
        uint64_t midu = mid >> 30, midd = mid & MASK30;
        return CalcMod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    uint64_t CalcMod(uint64_t x) {
        uint64_t xu = x >> 61, xd = x & MASK61;
        uint64_t res = xu + xd;
        if (res >= _MOD) res -= _MOD;
        return res;
    }

    void expand(int sz) {
        if (power.size() < sz + 1) {
            int pre_sz = power.size();
            power.resize(sz + 1);
            for (int i = pre_sz - 1 ; i < sz ; i++) {
                power[i + 1] = Mul(power[i], base);
            }
        }
    }

    RollingHash(uint64_t base = generateBase()) : base(base), power(1, 1) {}

    vector<uint64_t> buildTable(const string& str) {
        int sz = str.size();
        vector<uint64_t> hashed(sz + 1);
        for (int i = 0 ; i < sz ; i++) {
            hashed[i + 1] = CalcMod(Mul(hashed[i], base) + str[i]);
        }
        return hashed;
    }

    template <class T> vector<uint64_t> buildTable(const vector<T>& V) {
        int sz = V.size();
        vector<uint64_t> hashed(sz + 1);
        for (int i = 0 ; i < sz ; i++) {
            hashed[i + 1] = CalcMod(Mul(hashed[i], base) + V[i]);
        }
        return hashed;
    }

    uint64_t getHash(const vector<uint64_t> &H, int l, int r) {
        expand(r - l);
        return CalcMod(H[r] + POSITIVIZER - Mul(H[l], power[r - l]));
    }

    int lcp(const vector<uint64_t> &H1, int l1, int r1, const vector<uint64_t> &H2, int l2, int r2) {
        int len = min(r1 - l1, r2 - l2);
        int ok = 0, ng = len + 1;
        while (ok < ng - 1) {
            int mid = (ok + ng) / 2;
            if (getHash(H1, l1, l1 + mid) == getHash(H2, l2, l2 + mid)) ok = mid;
            else ng = mid;
        }
        return ok;
    }
};

int main() {
    int N, M;
    cin >> N >> M;
    string S; cin >> S;
    RollingHash roll;
    auto T = roll.buildTable(S);

    int l = 0, r = 1;

    set<uint64_t> st;

    for (int _ = 0 ; _ < M ; _++) {
        string Q; cin >> Q;
        if (Q == "L--") {
            l--;
        }
        else if (Q == "L++") {
            l++;
        }
        else if (Q == "R--") {
            r--;
        }
        else if (Q == "R++") {
            r++;
        }
        else {
            assert(!"input false!");
        }

        st.insert(roll.getHash(T, l, r));
    }

    cout << st.size() << endl;
}
accuracy: 1
time_ms: 120
memory_kb: 22812
final_rank: 9

code_snippet: #line 1 "test/aoj/aoj_2444.test.cpp"
#define PROBLEM \
    "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444&lang=jp"

#include <cassert>
#include <cstdint>
#include <iostream>
#include <set>
#include <string>
#include <vector>

#line 2 "string/rolling_hash.hpp"

#include <array>
#line 7 "string/rolling_hash.hpp"

#line 2 "utility/hash.hpp"

#line 4 "utility/hash.hpp"

#line 2 "utility/modint61.hpp"

#line 6 "utility/modint61.hpp"

#line 2 "utility/modint_base.hpp"

#include <type_traits>

namespace ebi {

namespace internal {

struct modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

}  // namespace ebi
#line 8 "utility/modint61.hpp"

namespace ebi {

struct modint61 : internal::modint_base {
  private:
    using mint = modint61;
    using u64 = std::uint64_t;
    constexpr static u64 m = (1ull << 61) - 1;
    constexpr static u64 MASK31 = (1ull << 31) - 1;
    constexpr static u64 MASK30 = (1ull << 30) - 1;

  public:
    constexpr static u64 mod() {
        return m;
    }

    constexpr modint61() : _v(0) {}

    constexpr modint61(long long v) {
        v %= (long long)umod();
        if (v < 0) v += (long long)umod();
        _v = u64(v);
    }

    constexpr u64 val() const {
        return _v;
    }

    constexpr u64 value() const {
        return val();
    }

    constexpr mint &operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }

    constexpr mint &operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }

    constexpr mint &operator+=(const mint &rhs) {
        _v += rhs._v;
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator-=(const mint &rhs) {
        if (_v < rhs._v) _v += umod();
        assert(_v >= rhs._v);
        _v -= rhs._v;
        return *this;
    }

    constexpr mint &operator*=(const mint &rhs) {
        u64 au = _v >> 31, ad = _v & MASK31;
        u64 bu = rhs._v >> 31, bd = rhs._v & MASK31;
        u64 mid = ad * bu + au * bd;
        u64 midu = mid >> 30;
        u64 midd = mid & MASK30;
        _v = (au * bu * 2 + midu + (midd << 31) + ad * bd);
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator/=(const mint &rhs) {
        return *this *= rhs.inv();
    }

    constexpr mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, res = 1;
        while (n) {
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }

    constexpr mint inv() const {
        assert(_v);
        return pow(umod() - 2);
    }

    friend mint operator+(const mint &lhs, const mint &rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint &lhs, const mint &rhs) {
        return lhs.val() == rhs.val();
    }
    friend bool operator!=(const mint &lhs, const mint &rhs) {
        return !(lhs == rhs);
    }
    friend bool operator<(const mint &lhs, const mint &rhs) {
        return lhs._v < rhs._v;
    }
    friend bool operator>(const mint &lhs, const mint &rhs) {
        return rhs < lhs;
    }

  private:
    u64 _v = 0;

    constexpr static u64 umod() {
        return m;
    }

    constexpr u64 safe_mod(const u64 &a) {
        u64 au = a >> 61;
        u64 ad = a & umod();
        u64 res = au + ad;
        if (res >= umod()) res -= umod();
        return res;
    }
};

}  // namespace ebi
#line 2 "utility/random_number_generator_64.hpp"

#line 4 "utility/random_number_generator_64.hpp"
#include <random>

namespace ebi {

struct random_number_generator_64 {
  private:
    using u64 = std::uint64_t;
    std::random_device rnd;
    std::mt19937_64 mt;

  public:
    random_number_generator_64() : mt(rnd()) {}

    u64 get(u64 a, u64 b) {
        std::uniform_int_distribution<u64> dist(a, b - 1);
        return dist(mt);
    }
};

}  // namespace ebi
#line 7 "utility/hash.hpp"

namespace ebi {

template <int BASE_NUM> struct Hash : std::array<modint61, BASE_NUM> {
  private:
    using std::array<modint61, BASE_NUM>::array;
    using std::array<modint61, BASE_NUM>::operator=;

  public:
    Hash() : std::array<modint61, BASE_NUM>() {}

    constexpr static Hash set(const modint61 &a) {
        Hash res;
        std::fill(res.begin(), res.end(), a);
        return res;
    }

    constexpr Hash &operator+=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator-=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator*=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs[i];
        }
        return *this;
    }

    constexpr Hash &operator+=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs;
        }
        return *this;
    }
    constexpr Hash &operator-=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs;
        }
        return *this;
    }
    constexpr Hash &operator*=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs;
        }
        return *this;
    }

    Hash operator+(const Hash &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const Hash &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const Hash &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash operator+(const modint61 &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const modint61 &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const modint61 &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash pow(long long n) const {
        Hash a = *this, res = set(1);
        while (n) {
            if (n & 1) res *= a;
            a *= a;
            n >>= 1;
        }
        return res;
    }

    static Hash get_basis() {
        static random_number_generator_64 rng;
        Hash h;
        for (int i = 0; i < BASE_NUM; i++) {
            h[i] = rng.get(0, modint61::mod() - 1) + 1;
        }
        return h;
    }

    static Hash get_basis_primitive() {
        static random_number_generator_64 rng;
        Hash h;
        for (int i = 0; i < BASE_NUM; i++) {
            while (!is_primitive(
                (h[i] = rng.get(0, modint61::mod() - 1) + 1).val()))
                ;
        }
        return h;
    }

  private:
    static bool is_primitive(long long x) {
        for (long long d : {2, 3, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321}) {
            if (modint61(x).pow((modint61::mod() - 1) / d).val() <= 1)
                return false;
        }
        return true;
    }
};

}  // namespace ebi
#line 10 "string/rolling_hash.hpp"

/*
    reference: https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
*/

namespace ebi {

template <int n> struct rolling_hash {
  private:
    static constexpr int h = 100;

    using Self = rolling_hash<n>;

    static void expand(int m) {
        int now = base_pow.size();
        while (now <= m) {
            now <<= 1;
        }
        if(int(base_pow.size()) == now) return;
        base_pow.reserve(now);
        while (int(base_pow.size()) < now) {
            base_pow.emplace_back(base_pow.back() * base);
        }
    }

  public:
    rolling_hash(const std::string &s) : sz(s.size()) {
        assert(n >= 0);
        hash.reserve(sz + 1);
        hash.emplace_back(Hash<n>::set(0));
        expand(sz);
        for (const auto &c : s) {
            hash.emplace_back(hash.back() * base + c + h);
        }
    }

    Hash<n> prefix_hash(int r) const {
        return hash[r];
    }

    // [l, r)
    Hash<n> get_hash(int l, int r) const {
        assert(0 <= l && l <= r && r <= sz);
        return prefix_hash(r) - prefix_hash(l) * base_pow[r - l];
    }

    static Hash<n> get_hash(const std::string &str, int l = 0, int r = -1) {
        if (r < 0) r = int(str.size());
        Hash<n> res = Hash<n>::set(0);
        for (int i = l; i < r; i++) {
            res = res * base + str[i] + h;
        }
        return res;
    }

    static Hash<n> concat(Self lhs, Self rhs) {
        return lhs.hash.back() * base_pow[rhs.size()] + rhs.hash.back();
    }

    int size() const {
        return sz;
    }

    static void set_base() {
        base = Hash<n>::get_basis_primitive();
        base_pow = std::vector<Hash<n>>(1, Hash<n>::set(1));
    }

    Self operator+(const Self &rhs) noexcept {
        return Self(*this) += rhs;
    }

    Self &operator+=(const Self &rhs) noexcept {
        Hash<n> a = hash.back();
        for(int i = 1; i <= rhs.size(); i++) {
            a *= base;
            hash.emplace_back(a + rhs.hash[i]);
        }
        sz += rhs.size();
        expand(sz);
        return *this;
    }

  private:
    int sz;
    std::vector<Hash<n>> hash;
    static Hash<n> base;
    static std::vector<Hash<n>> base_pow;
};

template <int n> Hash<n> rolling_hash<n>::base = {};
template <int n> std::vector<Hash<n>> rolling_hash<n>::base_pow = {};

}  // namespace ebi
#line 13 "test/aoj/aoj_2444.test.cpp"

using u64 = std::uint64_t;

int main() {
    int n, m;
    std::cin >> n >> m;
    std::string s;
    std::cin >> s;
    std::set<ebi::Hash<2>> set;
    ebi::rolling_hash<2>::set_base();
    ebi::rolling_hash<2> rh("");
    for (int i = 0; i < n; i++) {
        ebi::rolling_hash<2> r(std::string(s.substr(i, 1)));
        rh += r;
    }
    int l = 0;
    int r = 1;
    while (m--) {
        std::string q;
        std::cin >> q;
        if (q == "L++") {
            l++;
        } else if (q == "L--") {
            l--;
        } else if (q == "R++") {
            r++;
        } else if (q == "R--") {
            r--;
        } else {
            assert(0);
        }
        set.insert(rh.get_hash(l, r));
    }
    std::cout << int(set.size()) << '\n';
}
accuracy: 1
time_ms: 140
memory_kb: 35640
final_rank: 17

code_snippet: #line 1 "test/aoj/aoj_2444.test.cpp"
#define PROBLEM \
    "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444&lang=jp"

#include <cassert>
#include <cstdint>
#include <iostream>
#include <set>
#include <vector>

#line 2 "string/rolling_hash.hpp"

#include <array>
#line 7 "string/rolling_hash.hpp"

#line 2 "utility/hash.hpp"

#line 4 "utility/hash.hpp"

#line 2 "utility/modint61.hpp"

#line 6 "utility/modint61.hpp"

#line 2 "utility/modint_base.hpp"

#include <type_traits>

namespace ebi {

namespace internal {

struct modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

}  // namespace ebi
#line 8 "utility/modint61.hpp"

namespace ebi {

struct modint61 : internal::modint_base {
  private:
    using mint = modint61;
    using u64 = std::uint64_t;
    constexpr static u64 m = (1ull << 61) - 1;
    constexpr static u64 MASK31 = (1ull << 31) - 1;
    constexpr static u64 MASK30 = (1ull << 30) - 1;

  public:
    constexpr static u64 mod() {
        return m;
    }

    constexpr modint61() : _v(0) {}

    constexpr modint61(long long v) {
        v %= (long long)umod();
        if (v < 0) v += (long long)umod();
        _v = u64(v);
    }

    constexpr u64 val() const {
        return _v;
    }

    constexpr u64 value() const {
        return val();
    }

    constexpr mint &operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }

    constexpr mint &operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }

    constexpr mint &operator+=(const mint &rhs) {
        _v += rhs._v;
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator-=(const mint &rhs) {
        if (_v < rhs._v) _v += umod();
        assert(_v >= rhs._v);
        _v -= rhs._v;
        return *this;
    }

    constexpr mint &operator*=(const mint &rhs) {
        u64 au = _v >> 31, ad = _v & MASK31;
        u64 bu = rhs._v >> 31, bd = rhs._v & MASK31;
        u64 mid = ad * bu + au * bd;
        u64 midu = mid >> 30;
        u64 midd = mid & MASK30;
        _v = (au * bu * 2 + midu + (midd << 31) + ad * bd);
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator/=(const mint &rhs) {
        return *this *= rhs.inv();
    }

    constexpr mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, res = 1;
        while (n) {
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }

    constexpr mint inv() const {
        assert(_v);
        return pow(umod() - 2);
    }

    friend mint operator+(const mint &lhs, const mint &rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint &lhs, const mint &rhs) {
        return lhs.val() == rhs.val();
    }
    friend bool operator!=(const mint &lhs, const mint &rhs) {
        return !(lhs == rhs);
    }
    friend bool operator<(const mint &lhs, const mint &rhs) {
        return lhs._v < rhs._v;
    }
    friend bool operator>(const mint &lhs, const mint &rhs) {
        return rhs < lhs;
    }

  private:
    u64 _v = 0;

    constexpr static u64 umod() {
        return m;
    }

    constexpr u64 safe_mod(const u64 &a) {
        u64 au = a >> 61;
        u64 ad = a & umod();
        u64 res = au + ad;
        if (res >= umod()) res -= umod();
        return res;
    }
};

}  // namespace ebi
#line 2 "utility/random_number_generator_64.hpp"

#line 4 "utility/random_number_generator_64.hpp"
#include <random>

namespace ebi {

struct random_number_generator_64 {
  private:
    using u64 = std::uint64_t;
    std::random_device rnd;
    std::mt19937_64 mt;

  public:
    random_number_generator_64() : mt(rnd()) {}

    u64 get(u64 a, u64 b) {
        std::uniform_int_distribution<u64> dist(a, b - 1);
        return dist(mt);
    }
};

}  // namespace ebi
#line 7 "utility/hash.hpp"

namespace ebi {

template <int BASE_NUM> struct Hash : std::array<modint61, BASE_NUM> {
  private:
    using std::array<modint61, BASE_NUM>::array;
    using std::array<modint61, BASE_NUM>::operator=;

  public:
    Hash() : std::array<modint61, BASE_NUM>() {}

    constexpr static Hash set(const modint61 &a) {
        Hash res;
        std::fill(res.begin(), res.end(), a);
        return res;
    }

    constexpr Hash &operator+=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator-=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator*=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs[i];
        }
        return *this;
    }

    constexpr Hash &operator+=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs;
        }
        return *this;
    }
    constexpr Hash &operator-=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs;
        }
        return *this;
    }
    constexpr Hash &operator*=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs;
        }
        return *this;
    }

    Hash operator+(const Hash &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const Hash &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const Hash &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash operator+(const modint61 &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const modint61 &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const modint61 &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash pow(long long n) const {
        Hash a = *this, res = set(1);
        while (n) {
            if (n & 1) res *= a;
            a *= a;
            n >>= 1;
        }
        return res;
    }

    static Hash get_basis() {
        static random_number_generator_64 rng;
        Hash h;
        for (int i = 0; i < BASE_NUM; i++) {
            h[i] = rng.get(0, modint61::mod() - 1) + 1;
        }
        return h;
    }

    static Hash get_basis_primitive() {
        static random_number_generator_64 rng;
        Hash h;
        for (int i = 0; i < BASE_NUM; i++) {
            while (!is_primitive(
                (h[i] = rng.get(0, modint61::mod() - 1) + 1).val()))
                ;
        }
        return h;
    }

  private:
    static bool is_primitive(long long x) {
        for (long long d : {2, 3, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321}) {
            if (modint61(x).pow((modint61::mod() - 1) / d).val() <= 1)
                return false;
        }
        return true;
    }
};

}  // namespace ebi
#line 10 "string/rolling_hash.hpp"

/*
    reference: https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
*/

namespace ebi {

template <int n> struct rolling_hash {
  private:
    static constexpr int h = 100;

    static void expand(int m) {
        int now = base_pow.size();
        while(now <= m) {
            now <<= 1;
        }
        base_pow.reserve(now);
        while(int(base_pow.size()) < now) {
            base_pow.emplace_back(base_pow.back() * base);
        }
    }

  public:
    rolling_hash(const std::string &s) : sz(s.size()) {
        assert(n >= 0);
        hash.reserve(sz + 1);
        hash.emplace_back(Hash<n>::set(0));
        expand(sz);
        for (const auto &c : s) {
            hash.emplace_back(hash.back() * base + c + h);
        }
    }

    // [l, r)
    Hash<n> get_hash(int l, int r) const {
        assert(0 <= l && l <= r && r <= sz);
        return hash[r] - hash[l] * base_pow[r - l];
    }

    static Hash<n> get_hash(const std::string &str, int l = 0, int r = -1) {
        if (r < 0) r = int(str.size());
        Hash<n> res = Hash<n>::set(0);
        for (int i = l; i < r; i++) {
            res = res * base + str[i] + h;
        }
        return res;
    }

    Hash<n> concat(const Hash<n> &hash1, const Hash<n> &hash2, int len2) {
        return hash1 * base.pow(len2) + hash2;
    }

    static void set_base() {
        base = Hash<n>::get_basis_primitive();
        base_pow = std::vector<Hash<n>>(1, Hash<n>::set(1));
    }

  private:
    int sz;
    std::vector<Hash<n>> hash;
    static Hash<n> base;
    static std::vector<Hash<n>> base_pow;
};

template <int n> Hash<n> rolling_hash<n>::base = {};
template <int n> std::vector<Hash<n>> rolling_hash<n>::base_pow = {};

}  // namespace ebi
#line 12 "test/aoj/aoj_2444.test.cpp"

using u64 = std::uint64_t;

int main() {
    int n, m;
    std::cin >> n >> m;
    std::string s;
    std::cin >> s;
    std::set<ebi::Hash<2>> set;
    ebi::rolling_hash<2>::set_base();
    ebi::rolling_hash<2> rh(s);
    int l = 0;
    int r = 1;
    while (m--) {
        std::string q;
        std::cin >> q;
        if (q == "L++") {
            l++;
        } else if (q == "L--") {
            l--;
        } else if (q == "R++") {
            r++;
        } else if (q == "R--") {
            r--;
        } else {
            assert(0);
        }
        set.insert(rh.get_hash(l, r));
    }
    std::cout << int(set.size()) << '\n';
}
accuracy: 1
time_ms: 140
memory_kb: 34896
final_rank: 16

code_snippet: #line 1 "test/aoj/aoj_2444.test.cpp"
#define PROBLEM \
    "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444&lang=jp"

#include <cassert>
#include <cstdint>
#include <iostream>
#include <map>
#include <vector>

#line 2 "String/rolling_hash.hpp"

#include <array>
#line 7 "String/rolling_hash.hpp"

#line 2 "utility/hash.hpp"

#line 4 "utility/hash.hpp"

#line 2 "utility/modint61.hpp"

#line 6 "utility/modint61.hpp"

#line 2 "utility/modint_base.hpp"

#include <type_traits>

namespace ebi {

namespace internal {

struct modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

}  // namespace ebi
#line 8 "utility/modint61.hpp"

namespace ebi {

struct modint61 : internal::modint_base {
  private:
    using mint = modint61;
    using u64 = std::uint64_t;
    constexpr static u64 m = (1ull << 61) - 1;
    constexpr static u64 MASK31 = (1ull << 31) - 1;
    constexpr static u64 MASK30 = (1ull << 30) - 1;

  public:
    constexpr static u64 mod() {
        return m;
    }

    constexpr modint61() : _v(0) {}

    constexpr modint61(long long v) {
        v %= (long long)umod();
        if (v < 0) v += (long long)umod();
        _v = u64(v);
    }

    constexpr u64 val() const {
        return _v;
    }

    constexpr u64 value() const {
        return val();
    }

    constexpr mint &operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }

    constexpr mint &operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }

    constexpr mint &operator+=(const mint &rhs) {
        _v += rhs._v;
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator-=(const mint &rhs) {
        if (_v < rhs._v) _v += umod();
        assert(_v >= rhs._v);
        _v -= rhs._v;
        return *this;
    }

    constexpr mint &operator*=(const mint &rhs) {
        u64 au = _v >> 31, ad = _v & MASK31;
        u64 bu = rhs._v >> 31, bd = rhs._v & MASK31;
        u64 mid = ad * bu + au * bd;
        u64 midu = mid >> 30;
        u64 midd = mid & MASK30;
        _v = (au * bu * 2 + midu + (midd << 31) + ad * bd);
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator/=(const mint &rhs) {
        return *this *= rhs.inv();
    }

    constexpr mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, res = 1;
        while (n) {
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }

    constexpr mint inv() const {
        assert(_v);
        return pow(umod() - 2);
    }

    friend mint operator+(const mint &lhs, const mint &rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint &lhs, const mint &rhs) {
        return lhs.val() == rhs.val();
    }
    friend bool operator!=(const mint &lhs, const mint &rhs) {
        return !(lhs == rhs);
    }
    friend bool operator<(const mint &lhs, const mint &rhs) {
        return lhs._v < rhs._v;
    }
    friend bool operator>(const mint &lhs, const mint &rhs) {
        return rhs < lhs;
    }

  private:
    u64 _v = 0;

    constexpr static u64 umod() {
        return m;
    }

    constexpr u64 safe_mod(const u64 &a) {
        u64 au = a >> 61;
        u64 ad = a & umod();
        u64 res = au + ad;
        if (res >= umod()) res -= umod();
        return res;
    }
};

}  // namespace ebi
#line 2 "utility/random_number_generator_64.hpp"

#line 4 "utility/random_number_generator_64.hpp"
#include <random>

namespace ebi {

struct random_number_generator_64 {
  private:
    using u64 = std::uint64_t;
    std::random_device rnd;
    std::mt19937_64 mt;

  public:
    random_number_generator_64() : mt(rnd()) {}

    u64 get(u64 a, u64 b) {
        std::uniform_int_distribution<u64> dist(a, b - 1);
        return dist(mt);
    }
};

}  // namespace ebi
#line 7 "utility/hash.hpp"

namespace ebi {

template <int BASE_NUM> struct Hash : std::array<modint61, BASE_NUM> {
  private:
    using std::array<modint61, BASE_NUM>::array;
    using std::array<modint61, BASE_NUM>::operator=;

  public:
    Hash() : std::array<modint61, BASE_NUM>() {}

    constexpr static Hash set(const modint61 &a) {
        Hash res;
        std::fill(res.begin(), res.end(), a);
        return res;
    }

    constexpr Hash &operator+=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator-=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs[i];
        }
        return *this;
    }
    constexpr Hash &operator*=(const Hash &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs[i];
        }
        return *this;
    }

    constexpr Hash &operator+=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] += rhs;
        }
        return *this;
    }
    constexpr Hash &operator-=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] -= rhs;
        }
        return *this;
    }
    constexpr Hash &operator*=(const modint61 &rhs) {
        for (int i = 0; i < BASE_NUM; i++) {
            (*this)[i] *= rhs;
        }
        return *this;
    }

    Hash operator+(const Hash &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const Hash &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const Hash &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash operator+(const modint61 &rhs) const {
        return Hash(*this) += rhs;
    }
    Hash operator-(const modint61 &rhs) const {
        return Hash(*this) -= rhs;
    }
    Hash operator*(const modint61 &rhs) const {
        return Hash(*this) *= rhs;
    }

    Hash pow(long long n) const {
        Hash a = *this, res = set(1);
        while (n) {
            if (n & 1) res *= a;
            a *= a;
            n >>= 1;
        }
        return res;
    }

    static Hash get_basis() {
        static random_number_generator_64 rng;
        Hash h;
        for (int i = 0; i < BASE_NUM; i++) {
            while (!is_primitive(
                (h[i] = rng.get(0, modint61::mod() - 1) + 1).val()))
                ;
        }
        return h;
    }

  private:
    static bool is_primitive(long long x) {
        for (long long d : {2, 3, 5, 7, 11, 13, 31, 41, 61, 151, 331, 1321}) {
            if (modint61(x).pow((modint61::mod() - 1) / d).val() <= 1)
                return false;
        }
        return true;
    }
};

}  // namespace ebi
#line 10 "String/rolling_hash.hpp"

/*
    reference: https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
*/

namespace ebi {

template <int n> struct rolling_hash {
  private:
    using mint = modint61;
    static constexpr mint h = 100;

  public:
    rolling_hash(const std::string &s) : sz(s.size()) {
        assert(n >= 0);
        base_pow.reserve(sz + 1);
        base_pow.emplace_back(Hash<n>::set(1));
        hash.reserve(sz + 1);
        hash.emplace_back(Hash<n>::set(0));
        for (const auto &c : s) {
            hash.emplace_back(hash.back() * base + c + h);
            base_pow.emplace_back(base_pow.back() * base);
        }
    }

    // [l, r)
    Hash<n> get_hash(int l, int r) const {
        assert(0 <= l && l <= r && r <= sz);
        return hash[r] - hash[l] * base_pow[r - l];
    }

    static Hash<n> get_hash(const std::string &str, int l = 0, int r = -1) {
        if (r < 0) r = int(str.size());
        Hash<n> res = Hash<n>::set(0);
        for (int i = l; i < r; i++) {
            res = res * base + str[i] + h;
        }
        return res;
    }

    Hash<n> concat(const Hash<n> &hash1, const Hash<n> &hash2, int len2) {
        return hash1 * base.pow(len2) + hash2;
    }

    static void set_base() {
        base = Hash<n>::get_basis();
    }

  private:
    int sz;
    std::vector<Hash<n>> base_pow;
    std::vector<Hash<n>> hash;

  public:
    static Hash<n> base;
};

template <int n> Hash<n> rolling_hash<n>::base = {};

}  // namespace ebi
#line 12 "test/aoj/aoj_2444.test.cpp"

using u64 = std::uint64_t;

int main() {
    int n, m;
    std::cin >> n >> m;
    std::string s;
    std::cin >> s;
    std::map<std::array<ebi::modint61, 2>, int> map;
    ebi::rolling_hash<2>::set_base();
    ebi::rolling_hash<2> rh(s);
    int l = 0;
    int r = 1;
    while (m--) {
        std::string q;
        std::cin >> q;
        if (q == "L++") {
            l++;
        } else if (q == "L--") {
            l--;
        } else if (q == "R++") {
            r++;
        } else if (q == "R--") {
            r--;
        } else {
            assert(0);
        }
        map[rh.get_hash(l, r)] = 1;
    }
    std::cout << int(map.size()) << '\n';
}
accuracy: 1
time_ms: 120
memory_kb: 31500
final_rank: 13

code_snippet: #line 1 "test/aoj/aoj_2444.test.cpp"
#define PROBLEM \
    "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444&lang=jp"

#include <cassert>
#include <cstdint>
#include <iostream>
#include <map>
#include <vector>

#line 2 "String/rolling_hash.hpp"

#include <array>
#line 7 "String/rolling_hash.hpp"

#line 2 "utility/modint61.hpp"

#line 6 "utility/modint61.hpp"

#line 2 "utility/modint_base.hpp"

#include <type_traits>

namespace ebi {

namespace internal {

struct modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

}  // namespace ebi
#line 8 "utility/modint61.hpp"

namespace ebi {

struct modint61 : internal::modint_base {
  private:
    using mint = modint61;
    using u64 = std::uint64_t;
    constexpr static u64 m = (1ull << 61) - 1;
    constexpr static u64 MASK31 = (1ull << 31) - 1;
    constexpr static u64 MASK30 = (1ull << 30) - 1;

  public:
    constexpr static u64 mod() {
        return m;
    }

    constexpr modint61() : _v(0) {}

    constexpr modint61(long long v) {
        v %= (long long)umod();
        if (v < 0) v += (long long)umod();
        _v = u64(v);
    }

    constexpr u64 val() const {
        return _v;
    }

    constexpr u64 value() const {
        return val();
    }

    constexpr mint &operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }

    constexpr mint &operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }

    constexpr mint &operator+=(const mint &rhs) {
        _v += rhs._v;
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator-=(const mint &rhs) {
        if (_v < rhs._v) _v += umod();
        assert(_v >= rhs._v);
        _v -= rhs._v;
        return *this;
    }

    constexpr mint &operator*=(const mint &rhs) {
        u64 au = _v >> 31, ad = _v & MASK31;
        u64 bu = rhs._v >> 31, bd = rhs._v & MASK31;
        u64 mid = ad * bu + au * bd;
        u64 midu = mid >> 30;
        u64 midd = mid & MASK30;
        _v = (au * bu * 2 + midu + (midd << 31) + ad * bd);
        _v = safe_mod(_v);
        return *this;
    }

    constexpr mint &operator/=(const mint &rhs) {
        return *this *= rhs.inv();
    }

    constexpr mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, res = 1;
        while (n) {
            if (n & 1) res *= x;
            x *= x;
            n >>= 1;
        }
        return res;
    }

    constexpr mint inv() const {
        assert(_v);
        return pow(umod() - 2);
    }

    friend mint operator+(const mint &lhs, const mint &rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint &lhs, const mint &rhs) {
        return lhs.val() == rhs.val();
    }
    friend bool operator!=(const mint &lhs, const mint &rhs) {
        return !(lhs == rhs);
    }
    friend bool operator<(const mint &lhs, const mint &rhs) {
        return lhs._v < rhs._v;
    }
    friend bool operator>(const mint &lhs, const mint &rhs) {
        return rhs < lhs;
    }

  private:
    u64 _v = 0;

    constexpr static u64 umod() {
        return m;
    }

    constexpr u64 safe_mod(const u64 &a) {
        u64 au = a >> 61;
        u64 ad = a & umod();
        u64 res = au + ad;
        if (res >= umod()) res -= umod();
        return res;
    }
};

}  // namespace ebi
#line 2 "utility/random_number_generator_64.hpp"

#line 4 "utility/random_number_generator_64.hpp"
#include <random>

namespace ebi {

struct random_number_generator_64 {
  private:
    using u64 = std::uint64_t;
    std::random_device rnd;
    std::mt19937_64 mt;

  public:
    random_number_generator_64() : mt(rnd()) {}

    u64 get(u64 a, u64 b) {
        std::uniform_int_distribution<u64> dist(a, b - 1);
        return dist(mt);
    }
};

}  // namespace ebi
#line 10 "String/rolling_hash.hpp"

/*
    reference: https://qiita.com/keymoon/items/11fac5627672a6d6a9f6
*/

namespace ebi {

template <int n> struct rolling_hash {
  private:
    using mint = modint61;
    const mint h = 100;

  public:
    rolling_hash(const std::string &s) : sz(s.size()) {
        assert(n >= 0);
        for (int i = 0; i < n; ++i) {
            base_pow[i].reserve(sz + 1);
            base_pow[i].emplace_back(1);
            hash[i].reserve(sz + 1);
            hash[i].emplace_back(0);
            for (const auto &c : s) {
                hash[i].emplace_back(hash[i].back() * base[i] + c);
                base_pow[i].emplace_back(base_pow[i].back() * base[i]);
            }
        }
    }

    // [l, r)
    std::array<mint, n> get_hash(int l, int r) const {
        std::array<mint, n> ret;
        for (int i = 0; i < n; ++i) {
            ret[i] = hash[i][r] - hash[i][l] * base_pow[i][r - l];
        }
        return ret;
    }

    std::array<mint, n> get_hash(const std::string &str, int l = 0,
                              int r = -1) const {
        if (r < 0) r = int(str.size());
        std::array<mint, n> res(n, 0);
        for (int i = 0; i < n; ++i) {
            for (int j = l; j < r; ++j) {
                res[i] = res[i] * base[i] + str[i] + h;
            }
        }
        return res;
    }

    static void set_base() {
        random_number_generator_64 rnd;
        for (int i = 0; i < n; ++i) {
            base[i] = (1ull << 31) |  rnd.get(1, (1ull << 31) - 1) ;
        }
    }

  private:
    size_t sz;
    std::array<std::vector<mint>, n> base_pow;
    std::array<std::vector<mint>, n> hash;

  public:
    static std::array<mint, n> base;
};

template<int n>
std::array<modint61, n> rolling_hash<n>::base = {};

}  // namespace ebi
#line 12 "test/aoj/aoj_2444.test.cpp"

using u64 = std::uint64_t;

int main() {
    int n, m;
    std::cin >> n >> m;
    std::string s;
    std::cin >> s;
    std::map<std::array<ebi::modint61, 2>, int> map;
    ebi::rolling_hash<2>::set_base();
    ebi::rolling_hash<2> rh(s);
    int l = 0;
    int r = 1;
    while (m--) {
        std::string q;
        std::cin >> q;
        if (q == "L++") {
            l++;
        } else if (q == "L--") {
            l--;
        } else if (q == "R++") {
            r++;
        } else if (q == "R--") {
            r--;
        } else {
            assert(0);
        }
        map[rh.get_hash(l, r)] = 1;
    }
    std::cout << int(map.size()) << '\n';
}
accuracy: 1
time_ms: 120
memory_kb: 31432
final_rank: 12

code_snippet: #line 1 "test/string/aoj_2444.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2444&lang=jp"

#line 2 "template/template.hpp"

#include<bits/stdc++.h>
#line 5 "template/template.hpp"
#define rep(i,s,n) for (int i = s; i < (int)(n); i++)
#define all(v) v.begin(),v.end()

using ll = long long;
using ull = unsigned long long;

template<typename T> bool chmin(T &a, const T &b){
    if (a <= b) return false;
    a = b;
    return true;
}
template<typename T> bool chmax(T &a, const T &b){
    if (a >= b) return false;
    a = b;
    return true;
}
#line 2 "string/RollingHash.hpp"

#line 4 "string/RollingHash.hpp"


namespace lib{

using namespace std;

struct RollingHash {
    using ull = unsigned long long;
    RollingHash(const string &s = ""){ build(s);}
    ull get(int l, int r){
        assert(0 <= l && l <= r && r <= n);
        return cal(inner_hash[r] + buf - mul(inner_hash[l], pow_base[r-l]));
    }
    static ull get_hash(const string &s){
        int len = s.size();
        set_hash();
        extend_pow_base(len);
        ull res = 0;
        rep(i,0,len) res = cal(mul(res,BASE) + s[i]);
        return res;
    }
    static ull concat(const ull& hash1, const ull& hash2, const int& len2){
        return cal(cal(mul(hash1,pow_base[len2]))+hash2);
    }
  private:
    static constexpr ull MASK30 = (1ULL << 30) - 1;
    static constexpr ull MASK31 = (1ULL << 31) - 1;
    static constexpr ull MASK61 = (1ULL << 61) - 1;
    static constexpr ull MOD = (1ULL << 61) - 1;
    static constexpr ull buf = MOD * 4;
    static ull BASE;
    static vector<ull> pow_base;
    static ull mul(ull a, ull b){
        ull au = a >> 31, ad = a & MASK31;
        ull bu = b >> 31, bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30, midd = mid & MASK30;
        return (au * bu * 2 + midu + (midd << 31) + ad * bd);
    }
    static ull cal(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if (res >= MOD) res -= MOD;
        return res;
    }
    static void set_hash(){
        if (BASE == 0) BASE = (1UL<<31) + (random_device()() & MASK31);
    }
    static void extend_pow_base(int len){
        int nlen = pow_base.size();
        if (nlen > len) return ;
        pow_base.resize(len+1);
        rep(i,nlen,len+1) pow_base[i] = cal(mul(pow_base[i-1],BASE));
    }
    string str;
    int n;
    vector<ull> inner_hash;
    void build(const string &s){
        set_hash();
        str = s;
        n = s.size();
        extend_pow_base(n);
        inner_hash.resize(n+1);
        inner_hash[0] = 0;
        rep(i,0,n) inner_hash[i+1] = cal(mul(inner_hash[i],BASE) + s[i]);
    }
};
ull RollingHash::BASE = 0;
vector<ull> RollingHash::pow_base = vector<ull>(1,1);
using roriha = RollingHash;

} // namespace lib
#line 5 "test/string/aoj_2444.test.cpp"

int main() {
    int n,m;
    std::string s;
    std::cin >> n >> m >> s;
    lib::RollingHash rh(s);
    int l = 0, r = 1;
    std::set<ull> set;
    rep(i,0,m) {
        std::string q;
        std::cin >> q;
        if(q == "L++") {
            l++;
        }
        else if(q == "L--") {
            l--;
        }
        else if(q == "R++") {
            r++;
        }
        else {
            r--;
        }
        set.insert(rh.get(l, r));
    }
    std::cout << set.size() << '\n';
}
accuracy: 1
time_ms: 110
memory_kb: 22108
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define dump(x) cout << #x << " = " << (x) << endl;

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;

const ll mod1 = 1e9 + 7, mod2 = 1e9 + 9;
const ll base1 = 1e4 + 6, base2 = 1e4 + 8;

template<class T, T mod, T base>
struct rollinghash {
    vector<T> acum, powb;

    rollinghash(const string& s = "") {
        int n = (int)s.size();
        acum.resize(n + 1);
        powb.resize(n + 1);
        powb[0] = 1;

        for (int i = 0; i < n; i++) acum[i + 1] = (acum[i] * base + s[i]) % mod;
        for (int i = 0; i < n; i++) powb[i + 1] = powb[i] * base % mod;
    }

    T query(int l, int r) { //s1*c^(n-1)+s2*c^(n-2)+...+sn*c^0
        T res = acum[r] - acum[l] * powb[r - l] % mod;
        return (res + mod) % mod;
    }
};


int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);

    int n, m;
    string s;
    cin >> n >> m >> s;
    int l = 0, r = 1;
    set<pair<ll, ll>> st;
    rollinghash<ll, mod1, base1> rh1(s);
    rollinghash<ll, mod2, base2> rh2(s);
    while (m--) {
        string q;
        cin >> q;
        if (q == "L++") l++;
        else if (q == "L--") l--;
        else if (q == "R++") r++;
        else if (q == "R--") r--;
        int res1 = rh1.query(l, r);
        int res2 = rh2.query(l, r);
        st.insert({ res1, res2 });
    }
    cout << (int)st.size() << endl;
    
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 31380
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
// #include "../../string/rolling_hash.hpp"

struct RollingHash {
    static constexpr int M = 2;
    static constexpr long long MODS[M] = {999999937, 1000000007};
    static constexpr long long BASE = 9973;
    vector<long long> powb[M], hash[M];
    int n;
    RollingHash() {}
    RollingHash(const string& str) { init(str); }
    void init(const string& str) {
        n = str.size();
        for (int k = 0; k < M; k++) {
            powb[k].resize(n + 1, 1);
            hash[k].resize(n + 1, 0);
            for (int i = 0; i < n; i++) {
                hash[k][i + 1] = (hash[k][i] * BASE + str[i]) % MODS[k];
                powb[k][i + 1] = powb[k][i] * BASE % MODS[k];
            }
        }
    }
    // get hash str[l,r)
    long long get(int l, int r, int k) {
        long long res = hash[k][r] - hash[k][l] * powb[k][r - l] % MODS[k];
        if (res < 0) res += MODS[k];
        return res;
    }
};

bool match(RollingHash& rh1, int l1, int r1, RollingHash& rh2, int l2, int r2) {
    bool res = true;
    for (int k = 0; k < RollingHash::M; k++) {
        res &= rh1.get(l1, r1, k) == rh2.get(l2, r2, k);
    }
    return res;
}
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_14_B"
#define ll long long

int main() {
    ios_base::sync_with_stdio(0);
    string str, s;
    int n, q;
    cin>>n>>q; cin.ignore();
    getline(cin, str);

    RollingHash rh(str);
    set<pair<ll, ll>> st;
    int l=0, r=0;
    while(q--) {
        cin>>s;
        if(s=="L++") {
            l++;
        } else if(s=="L--") {
            l--;
        } else if(s=="R++") {
            r++;
        } else {
            r--;
        }
        assert(l>=0 && r>=0);
        st.insert({rh.get(l, r+1, 0), rh.get(l, r+1, 1)});
    }    
    cout<<st.size()<<'\n';
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 31368
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll a=1000000007;
int main(void){
    ll n,m;
    string s;
    cin>>n>>m>>s;
    ll l=0,r=0,v[n+1],p[n+1];
    v[0]=p[0]=1;
    set<ll> st;
    for(ll i=0;i<n;i++){
        v[i+1]=v[i]*a+s[i];
        p[i+1]=p[i]*a;
    }
    for(ll i=0;i<m;i++){
        string q;
        cin>>q;
        if(q=="R++"){
            r++;
        }else if(q=="R--"){
            r--;
        }else if(q=="L++"){
            l++;
        }else if(q=="L--"){
            l--;
        }
        st.insert(v[r+1]-v[l]*p[r-l+1]);
    }
    cout<<st.size()<<"\n";
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 22176
final_rank: 6